python - 如何告诉 POpen 使用/设置某些环境变量?
问题描述
我正在使用 Python 3.7 和 Django。我使用下面的命令来运行我通常会在 shell 中运行的命令......
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 使用我可以访问的相同 PATH。
解决方案
如果我们参考Popen 的文档,我们可以看到三个相关的论点:
cwd
str
orpath
-like 对象,即当前工作目录env
映射(比方说 adict
),这是传递给被调用程序的环境映射shell
标志,是否将程序包装在外壳中
让我们回顾一下每个解决方案。
如果你负担得起,就使用cwd="where is node"
,例如,如果node
是 in /usr/local/bin
,你可以使用cwd=/usr/local/bin
or 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,你可以,但这里是平台详细信息:
POSIX 平台
在 shell=True 的 POSIX 上,shell 默认为 /bin/sh。如果 args 是字符串,则该字符串指定要通过 shell 执行的命令。这意味着字符串的格式必须与在 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-fu,但需要注意的是:安全考虑。
奖金解决方案
只需在调用 Python 进程之前重新定义 PATH 即可。如果您使用的是 Django,您可以使用:
- 开发服务器
- 生产级服务器
在这两种情况下,您所要做的就是重新定义父进程的环境,对于像 Gunicorn 这样的生产级服务器,这是可能的,并且有文档可以做到这一点。对于开发服务器,请在您自己的 shell 级别执行此操作(但警告!您可能必须记录此类行为或告诉任何使用您的软件的人,您假设node
处于……大多数情况下是公平的路径)。
推荐阅读
- visual-studio - 创建单一表单应用程序
- r - 计算数据框中满足多个条件的行数
- python - VS 代码设置为使用 python 2.7,如何将其更改为 3.8?
- python - 使用 Matplotlib 绘图
- bash - Git Pre-Commit Hook: Unable to Run `dartfmt` (command not found) (Windows)
- javascript - 结果,我在最后一个函数中的数字旁边得到了 NaN
- xamarin - 按钮问题 xamarin
- html - Bootstrap4:手风琴折叠不平滑
- google-cloud-platform - 如何使 Google Cloud Run 使用 IPv4 而不是 IPv6 来容器应用程序
- c++ - 如何将字符串(或任何类型)存储到 T 类型的数组中?