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 关键字。)

4

2 回答 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

更新

FWIW,两者之间的区别在于第一种形式......

/bin/sh -c 'echo' '$ATESTVARIABLE'

...将只调用不带参数的shell内置echo,并设置$0为文字 string '$ATESTVARIABLE',例如...

$ /bin/sh -c 'echo $0'
/bin/sh
$ /bin/sh -c 'echo $0' '$ATESTVARIABLE'
$ATESTVARIABLE

...而第二种形式...

/bin/sh -c 'echo $ATESTVARIABLE'

echo...将使用等于环境变量值的单个参数调用 shell 的内置函数ATESTVARIABLE

于 2013-06-25T20:22:42.973 回答
4

实际上,以下代码有什么问题:

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

是您没有仔细阅读subprocess帮助页面

在 shell=True 的 Unix 上,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

它应该可以按您的预期工作!

否则,你对环境变量的理解是正确的。当您修改环境时,该环境将提供给当前进程的每个分叉子进程。

于 2013-06-25T21:23:53.500 回答