362

I believe that running an external command with a slightly modified environment is a very common case. That's how I tend to do it:

import subprocess, os
my_env = os.environ
my_env["PATH"] = "/usr/sbin:/sbin:" + my_env["PATH"]
subprocess.Popen(my_command, env=my_env)

I've got a gut feeling that there's a better way; does it look alright?

4

8 回答 8

514

我认为os.environ.copy()如果您不打算为当前进程修改 os.environ 会更好:

import subprocess, os
my_env = os.environ.copy()
my_env["PATH"] = "/usr/sbin:/sbin:" + my_env["PATH"]
subprocess.Popen(my_command, env=my_env)
于 2010-12-15T18:28:23.883 回答
91

这取决于问题是什么。如果要克隆和修改环境,一种解决方案可能是:

subprocess.Popen(my_command, env=dict(os.environ, PATH="path"))

但这在某种程度上取决于被替换的变量是有效的 python 标识符,它们最常见的是(您多久遇到不是字母数字+下划线或以数字开头的变量的环境变量名称?)。

否则,您可以编写如下内容:

subprocess.Popen(my_command, env=dict(os.environ, 
                                      **{"Not valid python name":"value"}))

在非常奇怪的情况下(您多久在环境变量名称中使用控制代码或非 ascii 字符?)环境的键是bytes您(在 python3 上)甚至不能使用该构造。

正如您所看到的,这里使用的技术(尤其是第一种)对环境的键有好处,通常是有效的 python 标识符,并且提前知道(在编码时),第二种方法有问题。如果不是这种情况,您可能应该寻找另一种方法

于 2015-03-11T14:38:32.833 回答
36

使用 Python 3.5,您可以这样做:

import os
import subprocess

my_env = {**os.environ, 'PATH': '/usr/sbin:/sbin:' + os.environ['PATH']}

subprocess.Popen(my_command, env=my_env)

在这里,我们最终得到了一个副本os.environ和覆盖的PATH值。

PEP 448 (Additional Unpacking Generalizations)使之成为可能。

另一个例子。如果你有一个默认环境(即os.environ),并且你想用一个 dict 覆盖默认值,你可以这样表达:

my_env = {**os.environ, **dict_with_env_variables}
于 2016-05-24T15:30:59.477 回答
25

如果在原始环境中以某种方式未定义,您可能会使用my_env.get("PATH", '')而不是,但除此之外它看起来很好。my_env["PATH"]PATH

于 2010-02-09T18:09:53.217 回答
13

要临时设置环境变量而不必复制 os.envrion 对象等,我这样做:

process = subprocess.Popen(['env', 'RSYNC_PASSWORD=foobar', 'rsync', \
'rsync://username@foobar.com::'], stdout=subprocess.PIPE)
于 2016-09-07T06:16:14.077 回答
5

env 参数接受字典。您可以简单地使用 os.environ,向其中添加一个键(您想要的变量)(如果必须,添加到 dict 的副本)并将其用作Popen.

于 2010-02-09T18:13:28.300 回答
2

我知道这已经回答了一段时间,但是有些人可能想知道关于在他们的环境变量中使用 PYTHONPATH 而不是 PATH 的一些要点。我已经概述了使用 cronjobs 运行 python 脚本的解释,这些脚本以不同的方式处理修改后的环境(在此处找到)。认为这对像我这样需要的比提供的答案多一点的人会有所帮助。

于 2013-07-16T22:21:44.153 回答
0

在某些情况下,您可能只想传递子流程所需的环境变量,但我认为您的想法总体上是正确的(我也是这样做的)。

于 2010-02-09T18:08:43.420 回答