我正在尝试更改Python执行过程的环境。似乎正确的方法应该是与os.environ进行交互。但是,我的以下断言失败了:
import os, subprocess
os.environ['ATESTVARIABLE'] = 'value'
value = subprocess.check_output(['echo', '$ATESTVARIABLE'], shell=True)
assert 'value' in value
我应该做些什么来改变当前的环境?上面的代码揭示了我对Python的理解中的哪些缺陷:)?
(请注意,在当前的Python解释器中,os.environ['ATESTVARIABLE']
包含期望值。我正在设置运行一些需要特定环境变量的代码,并且可能启动外部进程。显然,如果我想要控制特定子进程的环境,我使用env关键字。)
答案 0 :(得分:3)
查看subprocess
模块的源代码,这是因为使用shell=True
的参数列表将相当于......
/bin/sh -c 'echo' '$ATESTVARIABLE'
......当你想要的是......
/bin/sh -c 'echo $ATESTVARIABLE'
以下为我工作......
import os, subprocess
os.environ['ATESTVARIABLE'] = 'value'
value = subprocess.check_output('echo $ATESTVARIABLE', shell=True)
assert 'value' in value
<强>更新强>
FWIW,两者的区别在于第一种形式......
/bin/sh -c 'echo' '$ATESTVARIABLE'
...只会在没有参数的情况下调用shell的内置echo
,并将$0
设置为文字字符串'$ATESTVARIABLE'
,例如......
$ /bin/sh -c 'echo $0'
/bin/sh
$ /bin/sh -c 'echo $0' '$ATESTVARIABLE'
$ATESTVARIABLE
......而第二种形式......
/bin/sh -c 'echo $ATESTVARIABLE'
...将使用单个参数调用shell的内置echo
,该参数等于环境变量ATESTVARIABLE
的值。
答案 1 :(得分:3)
实际上,以下代码出了什么问题:
import os, subprocess
os.environ['ATESTVARIABLE'] = 'value'
value = subprocess.check_output(['echo', '$ATESTVARIABLE'], shell=True)
assert 'value' in value
是你没有彻底阅读 help page of subprocess:
在Unix上,shell = True,shell默认为/ bin / sh。如果args是一个字符串,则该字符串指定要通过shell执行的命令。这意味着字符串的格式必须与在shell提示符下键入时完全相同。这包括,例如,引用或反斜杠转义带有空格的文件名。 如果args是序列,则第一项指定命令字符串,任何其他项将被视为shell本身的附加参数。也就是说,Popen相当于:
Popen(['/bin/sh', '-c', args[0], args[1], ...])
这意味着如果您使用数组作为第一个参数调用subprocess.check_out()
,则无法获得预期结果。您将使用以下代码重试:
import os, subprocess
os.environ['ATESTVARIABLE'] = 'value'
value = subprocess.check_output('echo $ATESTVARIABLE', shell=True)
assert 'value' in value
它应该按预期工作!
否则,您对环境变量的理解是正确的。修改环境时,会将该环境提供给当前进程的每个分叉子级。