wim*_*wim 56 python environment subprocess path popen
我对subprocess使用时如何搜索可执行文件感到困惑Popen().如果给定子进程的绝对路径,它可以工作,但我正在尝试使用相对路径.我发现如果我设置环境变量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')])
Run Code Online (Sandbox Code Playgroud)
并且验证了在启动python时,无论是交互式地,使用ipython,还是通过从命令行运行脚本,PYTHONPATH都成功出现os.environ.但是,subrocess.Popen 仍然不在那里搜索可执行文件.如果没有env指定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()
Run Code Online (Sandbox Code Playgroud)
如果我在/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.
Wal*_*ndt 60
(从评论中填写详细信息以单独回答)
首先,无论你做什么,都不会在任何路径中检查相对路径(包含斜杠的路径).它们仅与当前工作目录相关.如果需要解析相对路径,则必须手动搜索PATH,或者使用PATH来包含子目录,然后使用命令名称,如下面的建议所示.
如果要运行相对于Python脚本位置的程序,请使用__file__并从那里查找程序的绝对路径,然后使用绝对路径Popen.
其次,Python bug跟踪器中存在一个问题,即Python如何处理裸命令(没有斜杠).基本上,在Unix/Mac上Popen使用os.execvp时调用shell=False,这意味着它会查看PATH Python启动时的值,并且没有任何更改os.environ可以帮助您解决这个问题.此外,在Windows上shell=False,它根本不关注PATH,只会查看相对于当前工作目录的内容.
如果你只是需要路径评估而不是真的想通过shell运行你的命令行,并且在UNIX上,我建议使用env而不是shell=True像在Popen(['/usr/bin/env', 'progtorun', other, args], ...).这允许您将不同的PATH传递给env进程,该进程将使用它来查找程序.它还避免了shell元字符的问题以及通过shell传递参数的潜在安全问题.显然,在Windows上(几乎是没有a的唯一平台/usr/bin/env),你需要做一些不同的事情.
nco*_*lan 12
你似乎对PATHand 的本质有点困惑PYTHONPATH.
PATH 是一个环境变量,告诉OS shell在哪里搜索可执行文件.
PYTHONPATH是一个环境变量,告诉Python解释器在哪里搜索要导入的模块.它与subprocess查找可执行文件无关.
由于底层实现的不同,subprocess.Popen默认情况下只会在非Windows系统上搜索路径(Windows总是会搜索一些系统目录,但这与PATH处理不同).扫描路径的唯一可靠的跨平台方法是传递shell=True给子进程调用,但这有其自身的问题(如Popen文档中所详述)
但是,看起来您的主要问题是您正在传递路径片段Popen而不是简单的文件名.只要你有一个目录分隔符,你就会禁用PATH搜索,即使在非Windows平台上也是如此(例如,请参阅exec系列函数的Linux文档).