如何在子流程模块打开的bash中添加环境变量?

时间:2019-01-10 07:15:00

标签: python subprocess

我需要在带有subprocess.call函数的Python脚本中使用wget,但是看来“ wget”命令无法由python打开的bash子进程识别。

我添加了环境变量(wget所在的路径):

export PATH=/usr/local/bin:$PATH

到我的Mac上的〜/ .bashrc文件和〜/ .bash_profile文件,并保证已将它们作为来源。 python脚本看起来像:

import subprocess as sp
cmd = 'wget'
process = sp.Popen(cmd ,stdout=sp.PIPE, stdin=sp.PIPE, 
stderr=sp.PIPE, shell=True ,executable='/bin/bash')
(stdoutdata, stderrdata) = process.communicate()
print stdoutdata, stderrdata

预期输出应为

wget: missing URL
Usage: wget [OPTION]... [URL]...

但是结果总是

/bin/bash: wget: command not found

有趣的是,如果我直接在bash终端中输入wget,我可以获得帮助输出,但是它在python脚本中永远无法工作。怎么可能呢?

PS:

如果我将命令更改为

cmd = '/usr/local/bin/wget'

然后它起作用。所以我确定我已经安装了wget。

1 个答案:

答案 0 :(得分:0)

您可以将env=参数传递给subprocess函数。

import os

myenv = os.environ.copy
myenv['PATH'] = '/usr/local/bin:' + myenv['PATH']
subprocess.run(..., env=myenv)

但是,您可能根本想避免运行shell,而是增加Python用于查找要在子进程调用中运行的二进制文件的PATH

import subprocess as sp
import os

os.environ['PATH'] = '/usr/local/bin:' + os.environ['PATH']
cmd = 'wget'
# use run instead of Popen
# don't needlessly use a shell
# and thus put [cmd] as a list
process = sp.run([cmd], stdout=sp.PIPE, stdin=sp.PIPE, 
stderr=sp.PIPE, 
    universal_newlines=True)
print(process.stdout, process.stderr)

Running Bash commands in Python详细解释了我所做的更改。

但是,没有充分的理由为此使用外部实用程序。 Python requests可以完成wget的所有工作,通常更自然,并且可以更好地控制其确切功能。