python子进程Popen环境路径?

python子进程Popen环境路径?,python,path,subprocess,environment,popen,Python,Path,Subprocess,Environment,Popen,我对使用Popen()时子流程如何搜索可执行文件感到困惑。如果给定子进程的绝对路径,它就可以工作,但我尝试使用相对路径。我发现,如果我设置了环境变量PYTHONPATH,那么我可以从该路径获得导入的模块ok,PYTHONPATH位于sys.path中,但它似乎对subprocess.Popen的行为没有帮助。我还尝试编辑sitecustomize.py文件,将PYTHONPATH添加到os.environ,如下所示 # copy PYTHONPATH environment variable i

我对使用
Popen()
子流程如何搜索可执行文件感到困惑。如果给定子进程的绝对路径,它就可以工作,但我尝试使用相对路径。我发现,如果我设置了环境变量PYTHONPATH,那么我可以从该路径获得导入的模块ok,PYTHONPATH位于
sys.path
中,但它似乎对
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时,或者通过从命令行运行脚本来启动python时,PYTHONPATH是否成功地出现在
os.environ
中。但是,
subprocess.Popen
仍然不会在那里搜索可执行文件。我以为它应该继承父环境,如果没有指定
env
kwarg?接下来,我尝试显式地给出
env
,首先是通过复制
os.getenv
,其次只是给出
env={'PATH':'/explicit/PATH/to/search/from'}
,它仍然找不到可执行文件。现在我被难倒了

希望一个例子能更清楚地解释我的问题:

/dir/subdir1/some_可执行文件
/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.environment['PATH']
中,子进程也不会抛出
OSError:[Errno 2]这样的文件或目录

pythonpath被设置为执行python解释器的路径。因此,在示例的第二种情况下,路径设置为/dir,而不是/dir/subdir2
这就是为什么会出现错误。

您似乎对
PATH
PYTHONPATH
的性质有点困惑

PATH
是一个环境变量,告诉操作系统外壳在哪里搜索可执行文件

PYTHONPATH
是一个环境变量,它告诉Python解释器在哪里搜索要导入的模块。它与查找可执行文件无关

由于底层实现的不同,
subprocess.Popen
默认情况下只会在非Windows系统上搜索路径(Windows有一些它总是搜索的系统目录,但这与
path
处理不同)。扫描路径的唯一可靠跨平台方法是将
shell=True
传递给子流程调用,但这有其自身的问题(如中所述)


但是,您的主要问题似乎是将路径片段传递给
Popen
,而不是简单的文件名。一旦有了目录分隔符,就要禁用
路径
搜索,即使是在非Windows平台上(例如,请参阅Linux文档了解相关信息)。

子流程中的相对路径。Popen的作用是相对于当前工作目录,而不是相对于系统路径的元素。如果从
/dir
运行
python subdir2/some_script.py
,则预期的可执行位置(传递到Popen)将是
/dir/./subdir1/some_executable
,也称为
/subdir/some_executable

如果您确实希望使用从脚本自己的目录到特定可执行文件的相对路径,那么最好的选择是首先从
\uuu文件\uuu
全局变量的目录部分构造一个绝对路径

#/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()
(填写评论中的详细信息以单独回答)

首先,无论您做什么,相对路径(包含斜杠的路径)都不会在任何
路径中进行检查。它们仅与当前工作目录相关。如果需要解析相对路径,则必须手动搜索
路径
,或者使用
路径
包含子目录,然后只需使用我下面建议的命令名即可

如果要相对于Python脚本的位置运行程序,请使用
\uuuuu file\uuuu
并从中查找程序的绝对路径,然后使用
Popen
中的绝对路径

在当前进程的环境变量中搜索
PATH
其次,介绍Python如何处理裸命令(无斜杠)。基本上,在Unix/Mac上,当参数
env=None
时,其行为类似于
os.execvp
(在末尾观察到并注意到一些意外行为):

在POSIX上,类使用类似于
os.execvp()
的行为来执行子程序

这实际上适用于
shell=False
shell=true
,前提是
env=None
。函数的文档中解释了此行为的含义:

在末尾附近包含一个“p”的变体(
execlp()
execlpe()
execvp()
,和
execvpe()
)将使用
路径
环境变量来定位程序文件。更换环境时(使用下一段中讨论的
exec*e
变体之一),新环境将用作
PATH
变量的源

#/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()
对于
execle();函数
execl()
execlp()
execv()
execvp()
都会导致新进程继承