我正在使用Python 3.7和Django。我使用下面的命令运行通常会在外壳中运行的命令...
out = Popen([settings.SELENIUM_RUNNER_CMD, file_path], stderr=STDOUT, stdout=PIPE)
t = out.communicate()[0], out.returncode
他死于错误
b'env: node: No such file or directory\n'
我要弄清楚的是如何让我的Python环境访问我可以访问的普通环境变量,或者想出一种在运行Python命令之前设置它们的方法。通常,当我自己检查时很容易找到“节点”
davea$ which node
/usr/local/bin/node
但是我不知道如何告诉Python使用我可以访问的相同路径。
答案 0 :(得分:4)
如果我们引用Popen's documentation,我们可以看到三个相关的参数:
cwd
str
或类似path
的对象,这是当前的工作目录env
映射(比方说dict
),这就是传递给被调用程序的环境映射shell
标志,无论是否将程序包装在外壳中让我们查看每种解决方案。
如果负担得起,只需使用cwd="where is node"
,例如,如果node
位于/usr/local/bin
中,则可以使用cwd=/usr/local/bin
或cwd=os.path.join(USR_LOCAL, 'bin')
例。但是,所有内容都将在此文件夹中创建,而这可能不是您想要的(日志,当前工作目录上的假设)。
现在,针对环境:
如果env不为None,则它必须是为新进程定义环境变量的映射。这些是用来代替继承当前流程环境的默认行为的。它直接传递给Popen。
您可以通过os.environ
复制当前环境,并在PATH
中添加如下内容:
new_env = os.environ.copy()
new_env['PATH'] = '{}:/usr/local/bin'.format(new_env['PATH'])
然后通过此new_env
映射,您就可以了!
如果您真的想依赖shell,可以,但是这里是平台详细信息:
在shell = True的POSIX上,shell默认为/ bin / sh。如果args是字符串,则该字符串指定要通过外壳执行的命令。这意味着字符串的格式必须与在shell提示符下键入时的格式完全相同。例如,这包括在文件名中使用引号或反斜杠转义。如果args是序列,则第一项指定命令字符串,任何其他项都将被视为shell本身的其他参数。也就是说,Popen等效于:
Popen(['/bin/sh', '-c', args[0], args[1], ...])
在shell = True的Windows上,COMSPEC环境变量指定默认的shell。在Windows上唯一需要指定shell = True的时间是将要执行的命令内置到shell中(例如dir或copy)。您不需要shell = True即可运行批处理文件或基于控制台的可执行文件。
您可以使用PATH=whatever
之类的东西并直接使用整个shell,但是要注意的是:安全注意事项。
只需在调用Python进程之前重新定义PATH。如果您使用的是Django,则可以使用:
在两种情况下,您要做的就是重新定义父进程的环境,对于Gunicorn这样的生产级服务器来说,这是可能的,并且有文档可以做到。对于开发服务器,请在您自己的外壳程序级别上进行操作(但请注意!您可能不得不记录这种行为,或者告诉任何使用您的软件的人,您假设node
处于……大多数情况下公平)。
答案 1 :(得分:0)
os.environ.copy()
最适合您的需求。
import subprocess, os
my_env = os.environ.copy()
out = Popen([settings.SELENIUM_RUNNER_CMD, file_path], stderr=STDOUT, stdout=PIPE, env=my_env)
t = out.communicate()[0], out.returncode
就应该了!