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()
都会导致新进程继承