为什么子进程忽略 PATH,我该如何改变它? [英] Why is subprocess ignoring PATH, and how can I change this?
问题描述
我需要更改 Python 应用程序调用的程序.不幸的是我无法更改 Python 代码.我只能改变调用环境(特别是PATH
).但不幸的是 Python 的 subprocess 模块似乎忽略了 PATH
(至少在某些情况下).
I need to change which program is called by a Python application. Unfortunately I cannot change the Python code. I can only change the calling environment (in particular, PATH
). But unfortunately Python’s subprocess module seems to ignore PATH
(at least under certain circumstances).
在搜索要调用的二进制文件时,如何强制 Python 遵守 PATH
?
为了说明问题,这里有一个 MVCE.实际的 Python 应用程序使用的是 subprocess.check_output(['nvidia-smi', '-L'])
,但以下简化代码显示了相同的行为.
To illustrate the problem, here’s an MVCE. The actual Python application is using subprocess.check_output(['nvidia-smi', '-L'])
, but the following simplified code shows the same behaviour.
创建test.py
:
import os
from subprocess import run
run(['which', 'whoami'])
run(['/usr/bin/env', 'whoami'])
run(['whoami'])
os.execvp('whoami', ['whoami'])
现在创建一个本地whoami
脚本并执行test.py
:
Now create a local whoami
script and execute test.py
:
echo 'echo foobar' >whoami
chmod +x whoami
PATH=.:$PATH python3 test.py
在我的系统1上打印:
./whoami
foobar
konrad
konrad
我期望这段代码总是打印foobar
而不是konrad
.
I expect this code to always print foobar
instead of konrad
.
我的 MVCE 包括 os.execvp
调用,因为 subprocess
文档 指出
My MVCE includes the os.execvp
call because the subprocess
documentation states that
在 POSIX 上,该类使用类似 os.execvp()
的行为来执行子程序.
On POSIX, the class uses
os.execvp()
-like behavior to execute the child program.
不用说,实际 execvp
POSIX API,从C调用,确实尊重PATH
,所以这是 Python 特定的问题.
Needless to say, the actual execvp
POSIX API, called from C, does respect PATH
, so this is a Python specific issue.
1 Ubuntu 18.04.2 LTS,Python 3.6.9.
1 Ubuntu 18.04.2 LTS, Python 3.6.9.
推荐答案
根据我的评论,这是由于 Python 对 execvp
与 POSIX 不一致 execvp
语义.特别是 Python 不响应ENOEX代码> 错误
将文件解释为 shell 脚本并需要显式shebang.
as per my comment, this is due to Python's implementation of execvp
not being consistent with POSIX execvp
semantics. in particular Python doesn't respond to ENOEXEC
errors by interpreting the file as a shell script and needs an explicit shebang.
创建文件为:
printf '#!/bin/sh\necho foobar\n' > ./whoami
使事情按预期工作
请注意,这已经有一段时间了:https://bugs.python.org/issue19948
note that this has been known about for a while: https://bugs.python.org/issue19948
这篇关于为什么子进程忽略 PATH,我该如何改变它?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!