我对使用Popen()
时subprocess
如何搜索可执行文件感到困惑。如果给定子进程的绝对路径,它就可以工作,但我尝试使用相对路径。我发现,如果设置环境变量PYTHONPATH,那么可以从该路径获取导入的模块,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时,或通过从命令行运行脚本时,PYTHONPATH是否成功出现在os.environ
中。但是,subrocess.Popen
仍然没有在那里搜索可执行文件。我想如果没有指定env
kwarg,它应该继承父环境?接下来,我尝试显式地给出env
,首先复制os.getenv
,然后只给出env={'PATH': '/explicit/path/to/search/from'}
,它仍然找不到可执行文件。现在我被难住了。
希望一个例子能更清楚地解释我的问题:
/dir/subdir1/some_可执行文件
/目录/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
。
(从评论中填写细节,单独作答)
首先,相对路径(包含斜线的路径)永远不会签入任何路径,无论您做什么。它们仅与当前工作目录相关。如果需要解析相对路径,则必须手动搜索该路径,或者将该路径修改为包含子目录,然后使用命令名,如下面的建议所示。
如果要相对于Python脚本的位置运行程序,请使用
__file__
,然后从中查找程序的绝对路径,然后使用Popen
中的绝对路径。其次,还有an issue in the Python bug tracker关于Python如何处理裸命令(没有斜杠)。基本上,在Unix/Mac上,
Popen
使用os.execvp
调用时使用shell=False
,这意味着它会像Python启动时那样查看PATH
的值,任何更改都不会帮助您解决这个问题。另外,在具有shell=False
的Windows上,它根本不关注路径,只会查找相对于当前工作目录的路径。如果您只需要路径计算,而不想通过shell运行命令行,并且是在UNIX上,我建议您使用
env
,而不是shell=True
,如Popen(['/usr/bin/env', 'progtorun', other, args], ...)
。这允许您将不同的路径传递给env
进程,该进程将使用它来查找程序。它还避免了shell元字符的问题和通过shell传递参数的潜在安全问题。显然,在Windows(几乎是唯一没有/usr/bin/env
的平台)上,您需要做一些不同的事情。你似乎对
PATH
和PYTHONPATH
的性质有点困惑。PATH
是一个环境变量,它告诉OS shell在哪里搜索可执行文件。PYTHONPATH
是一个环境变量,它告诉Python解释器在哪里搜索要导入的模块。它与查找可执行文件无关。由于底层实现的不同,} documentation 中所述)
subprocess.Popen
将只在非Windows系统上默认搜索路径(Windows有一些它总是搜索的系统目录,但这与PATH
处理不同)。扫描路径的唯一可靠跨平台方法是将shell=True
传递给子进程调用,但这有其自身的问题(如^{但是,您的主要问题似乎是,您将路径片段传递给
Popen
,而不是简单的文件名。一旦有了目录分隔符,就要禁用PATH
搜索,即使是在非Windows平台上(例如,请参阅Linux文档中的exec family of functions)。Popen中的相对路径相对于当前工作目录,而不是系统路径的元素。如果从
/dir
运行python subdir2/some_script.py
,则预期的可执行位置将是/dir/../subdir2/some_executable
,也就是/subdir2/some_executable
。如果您确实希望使用从脚本自己的目录到特定可执行文件的相对路径,最好的选择是首先从
__file__
全局变量的目录部分构造绝对路径。相关问题 更多 >
编程相关推荐