如何在Python中控制进程环境变量?

8

我想改变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关键字。)


你的代码不是有效的Python代码,抱歉。如果你希望得到帮助,请修复它。 - Paul
@paul- 我的代码在Linux和Python 2.7.3上执行(除了预期的AssertionError之外)。你使用的是哪个版本的Python? - dbn
啊,我明白了,你指的是check_output中已经更正的拼写错误。谢谢。 - dbn
2个回答

5

浏览 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

更新

顺便说一下,这两者之间的区别在于第一个表单...

/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的值。


4

以下代码有什么问题:

import os, subprocess
os.environ['ATESTVARIABLE'] = 'value'
value = subprocess.check_output(['echo', '$ATESTVARIABLE'], shell=True)
assert 'value' in value

你没有仔细阅读subprocess的帮助页面:http://docs.python.org/2/library/subprocess.html#popen-constructor
在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

并且它应该按照您的期望工作!

否则,您对环境变量的理解是正确的。当您修改环境时,该环境会被赋予当前进程的所有分支子进程。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接