python子进程Popen环境PATH?

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/subdir2os.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),你需要做一些不同的事情.

  • +1"此外,在Windows上,shell = False,它根本不关注PATH,只会查看相对于当前工作目录的信息." 刚刚帮我解决了一个大问题 - 谢谢! (6认同)
  • 在Windows上也应该使用的一种简单方法是,将os.environ ['PATH']`作为参数env赋予subprocess.Popen,如下所示:http://stackoverflow.com/a/ 4453495/1959808及其那里:http://stackoverflow.com/a/20669704/1959808。 (2认同)

nco*_*lan 12

你似乎对PATHand 的本质有点困惑PYTHONPATH.

PATH 是一个环境变量,告诉OS shell在哪里搜索可执行文件.

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

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

但是,看起来您的主要问题是您正在传递路径片段Popen而不是简单的文件名.只要你有一个目录分隔符,你就会禁用PATH搜索,即使在非Windows平台上也是如此(例如,请参阅exec系列函数的Linux文档).

  • 这与Python文档不匹配.[Popen docs](http://docs.python.org/library/subprocess.html)声明该程序是通过`os.execvp`执行的 - 并且该调用DOES考虑了PATH环境变量.另外,如果你只需要路径评估,我建议使用`env`而不是`shell = True`,如`Popen(['/ usr/bin/env','progtorun',other,args],... )`.这避免了shell元字符的问题以及通过shell传递参数的潜在安全问题. (3认同)
  • 更新以清楚地表明,默认情况下不搜索PATH是仅限Windows的事情,而且还指出真正的问题(要执行的命令中的目录分隔符). (2认同)