Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/362.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何从Python执行批处理文件,以便它能够改变调用进程的环境?_Python_Windows_Shell - Fatal编程技术网

如何从Python执行批处理文件,以便它能够改变调用进程的环境?

如何从Python执行批处理文件,以便它能够改变调用进程的环境?,python,windows,shell,Python,Windows,Shell,在Windows上,我想在python脚本中使用第三方命令行工具。假设它是foobar.exe位于C:\ProgramFiles(x86)\foobar下。Foobar附带了一个额外的批处理文件init_env.bat,该文件将为运行Foobar.exe设置shell环境 我想编写一个python脚本,它将首先调用init_env.bat一次,然后调用foobar.exe多次。然而,我所知道的所有机制(、和backticks)似乎都会为每次执行生成一个新的进程。因此,调用init_env.bat

在Windows上,我想在python脚本中使用第三方命令行工具。假设它是
foobar.exe
位于
C:\ProgramFiles(x86)\foobar
下。Foobar附带了一个额外的批处理文件
init_env.bat
,该文件将为运行
Foobar.exe
设置shell环境

我想编写一个python脚本,它将首先调用
init_env.bat
一次,然后调用
foobar.exe
多次。然而,我所知道的所有机制(、和backticks)似乎都会为每次执行生成一个新的进程。因此,调用
init_env.bat
是无用的,因为它不会改变python脚本运行的进程的环境,因此对
foobar.exe
的每个后续调用都会失败,因为它的环境没有设置

是否可以从python中调用
init_env.bat
,以允许
init_env.bat
改变调用脚本过程的环境

是否可以从python中以允许的方式调用
init_env.bat
init_env.bat
更改调用脚本的环境 过程

虽然不容易,但是如果
init_env.bat
非常简单,您可以尝试解析它,并自己对
os.environ
进行更改

否则,在子shell中生成它就容易多了,然后调用
set
来输出新的环境变量,并解析其中的输出

以下是我的作品

init_env.bat

@echo off
set FOO=foo
set BAR=bar
@echo off
echo FOO=%FOO%
echo BAR=%BAR%
foobar.bat

@echo off
set FOO=foo
set BAR=bar
@echo off
echo FOO=%FOO%
echo BAR=%BAR%
main.py

import sys, os, subprocess


INIT_ENV_BAT = 'init_env.bat'
FOOBAR_EXE = 'foobar.bat'


def init_env():
    vars = subprocess.check_output([INIT_ENV_BAT, '&&', 'set'], shell=True)
    for var in vars.splitlines():
        k, _, v = map(str.strip, var.strip().partition('='))
        if k.startswith('?'):
            continue
        os.environ[k] = v


def main():
    init_env()
    subprocess.check_call(FOOBAR_EXE, shell=True)
    subprocess.check_call(FOOBAR_EXE, shell=True)


if __name__ == '__main__':
    main()
…为其
python main.py
输出

FOO=foo
BAR=bar
FOO=foo
BAR=bar
请注意,我只使用批处理文件来代替您的
foobar.exe
,因为我手边没有可以确认环境变量已设置的
.exe
文件


如果您使用的是
.exe
文件,则可以从
子流程的行中删除
shell=True
子句。检查调用(FOOBAR\u exe,shell=True)

除非需要,否则不应传递
shell=True
。这里不需要它。@Piotrdorogost经过测试,看起来这两种方式都无关紧要。执行批处理文件时,即使没有
shell=True
,它也会生成一个shell
subprocess.check_调用(['foo.bat','>','foo.bat'])
仍然会影响
foo.bat
,因此可以说最好将其显式化,这样我们显然需要注意参数。好主意!谢谢对于Python 3的支持,我需要添加
var=var.decode('cp1252')
我不得不修改一行
k,v=map(str.strip,var.decode().strip().partition('='))
,因为我得到了错误:
TypeError:需要一个类似字节的对象,而不是'str'