python子进程Popen环境PATH?

| 我对使用
Popen()
subprocess
如何搜索可执行文件感到困惑。如果给子进程指定了绝对路径,那么它就可以工作,但是我正在尝试使用相对路径。我发现,如果我设置环境变量PYTHONPATH,则可以从该路径中获取导入的模块,并且PYTHONPATH在ѭ2ON中存在,但似乎对
subprocess.Popen
的行为没有帮助。我还尝试编辑
sitecustomize.py
文件,将PYTHONPATH添加到
os.environ
,就像这样
# copy PYTHONPATH environment variable into PATH to allow our stuff to use
# relative paths for subprocess spawning
import os
if os.getenv(\'PYTHONPATH\') is not None and os.getenv(\'PATH\') is not none:
    os.environ[\'PATH\'] = \':\'.join([os.getenv(\'PATH\'), os.getenv(\'PYTHONPATH\')])
并验证了在以交互方式,与ipython或通过从命令行运行脚本启动python时,PYTHONPATH已成功显示在
os.environ
中。但是,
subrocess.Popen
仍未在其中搜索可执行文件。如果没有指定no9 environment kwarg,我以为应该继承父母的环境?接下来,我尝试显式给出
env
,首先复制
os.getenv
,然后仅给出
env={\'PATH\': \'/explicit/path/to/search/from\'}
,但仍然找不到可执行文件。现在我很困惑。 希望有一个例子可以帮助我更清楚地解释我的问题: / dir / subdir1 / some_executable /dir/subdir2/some_script.py
# some_script.py
from subprocess import Popen, PIPE
spam, eggs = Popen([\'../subdir1/some_executable\'], stdout=PIPE, stderr=PIPE).communicate()
如果我在
/dir/subdir2
中运行
python some_script.py
就可以,但是如果我在
/dir
中运行
python subdir2/some_script.py
,即使
/dir/subdir2
os.environ[\'PATH\']
中,则子进程将抛出
OSError: [Errno 2] No such file or directory
。     
已邀请:
(填写评论的详细信息以做出单独的答案) 首先,无论您做什么,都不会在任何PATH中检查相对路径(包含斜杠的路径)。它们仅相对于当前工作目录。如果您需要解析相对路径,则必须手动搜索PATH,或者对PATH进行修改以使其包含子目录,然后按照下面的建议使用命令名即可。 如果要相对于Python脚本的位置运行程序,请使用
__file__
,然后从那里查找程序的绝对路径,然后在
Popen
中使用绝对路径。 其次,Python错误跟踪器中存在一个有关Python如何处理裸命令(无斜杠)的问题。基本上,在Unix / Mac上,
Popen
shell=False
一起调用时会使用
os.execvp
,这意味着它看起来像launched Python启动时的ѭ26value一样,没有任何变化的
os.environ
可以帮助您解决此问题。同样,在Windows XP中,如果使用
shell=False
,它根本不会关注PATH,而只会相对于当前工作目录进行查找。 如果您只需要路径评估,而又不想真正通过命令行运行命令行,并且在UNIX上,建议您使用
env
而不是
shell=True
,如
Popen([\'/usr/bin/env\', \'progtorun\', other, args], ...)
。这使您可以将不同的PATH传递给
env
进程,该进程将使用它来查找程序。它还避免了外壳元字符的问题和通过外壳传递参数的潜在安全问题。显然,在Windows(几乎是唯一没有
/usr/bin/env
的平台)上,您将需要做一些不同的事情。     
您似乎对
PATH
PYTHONPATH
的性质有些困惑。
PATH
是一个环境变量,它告诉OS Shell在哪里搜索可执行文件。
PYTHONPATH
是一个环境变量,它告诉Python解释器在哪里搜索要导入的模块。与ѭ0查找可执行文件无关。 由于底层实现的差异,在非Windows系统上,默认情况下,ѭ3将仅搜索路径(Windows始终会搜索某些系统目录,但这与
PATH
处理是不同的)。扫描路径的唯一可靠的跨平台方法是将
shell=True
传递给子流程调用,但这有其自身的问题(如
Popen
文档中所述) 但是,看来您的主要问题是您正在将路径片段传递给
Popen
而不是简单的文件名。一旦有了目录分隔符,即使在非Windows平台上,也要禁用
PATH
搜索(例如,请参见Linux文档中的exec系列功能)。     
subprocess.Popen中的相对路径相对于当前工作目录而不是系统PATH的元素起作用。如果您从
/dir
运行
python subdir2/some_script.py
,则预期的可执行位置将是
/dir/../subdir2/some_executable
,也就是
/subdir2/some_executable
。 如果您绝对想使用从脚本自己的目录到特定可执行文件的相对路径,最好的选择是首先从
__file__
全局变量的目录部分构造一个绝对路径。
#/usr/bin/env python
from subprocess import Popen, PIPE
from os.path import abspath, dirname, join
path = abspath(join(dirname(__file__), \'../subdir1/some_executable\'))
spam, eggs = Popen(path, stdout=PIPE, stderr=PIPE).communicate()
    
pythonpath设置为执行python解释器的路径。因此,在您的示例的第二种情况下,路径设置为/ dir而不是/ dir / subdir2 这就是为什么您会得到一个错误。     

要回复问题请先登录注册