【问题标题】:Subprocess.call or Subprocess.Popen cannot use executables that are in PATH (Linux/Windows)Subprocess.call 或 Subprocess.Popen 不能使用 PATH (Linux/Windows) 中的可执行文件
【发布时间】:2013-01-18 17:21:24
【问题描述】:

我正在编写一个需要在 Linux 和 Windows 上运行并使用路径中存在的可执行文件(带参数)的程序。 (假设)

目前我在使用 Subprocess.Call 和 Subprocess.Popen 在 Windows 中运行可执行文件时遇到问题。

对于这样的代码,在 Windows 8 中

def makeBlastDB(inFile, inputType, dbType, title, outDir):
    strProg = 'makeblastdb'
    strInput = '-in ' + inFile
    strInputType = '-input_type ' + inputType
    strDBType = '-dbtype ' + dbType
    strTitle = '-title ' + title
    strOut = '-out ' + os.path.join(os.sep, outDir, title)
    cmd = [strProg, strInput, strInputType, strDBType, strTitle, strOut]
    result = Popen(cmd, shell=True)

我在控制台中收到错误消息

'makeblastdb' is not recognized as an internal or external command,
operable program or batch file.

即使我可以使用 cmd.exe 运行相同的命令 我使用 shell=False 得到相同的响应。

假设可执行文件位于 PATH 环境变量中,关于如何运行命令的任何想法?谢谢

【问题讨论】:

  • 只需编写一个简单的脚本将可执行文件添加到您的路径中,或者您可以提供可执行文件的完整路径。
  • 我真的不想走那条路,因为可执行文件是第三方的,这意味着它可以安装在任何地方。
  • 它可以在 shell 中工作吗?你比较过echo %PATH%os.environ['PATH']吗?
  • @JFSebastian 这个问题已经超过 3 年了,OP 已经以某种方式解决了他们的问题(答案很可疑),我不确定你会从这里获得更多信息...... ;) 它可能是不同的 cwd 或一些糟糕的 windows 怪异,因为接受的答案没有多大意义。
  • @wim:如果 OP 不会更新问题,那么它应该被关闭为不可重现(因为显然subprocess.Popen 可以运行(至少一些)在 Linux 和 Windows 上的 PATH 中的可执行文件)。

标签: python windows shell subprocess


【解决方案1】:

您可以通过传递带有env 关键字参数的映射来控制生成的子进程中可用的环境变量。例如

proc = subprocess.Popen(args, env={'PATH': '/some/path'})

或者从系统环境变量继承PATH,而不必从系统环境中插入其他所有内容:

proc = subprocess.Popen(args, env={'PATH': os.getenv('PATH')})

不过,使用绝对路径可能更容易/更简单。

【讨论】:

  • 谢谢。关于绝对路径,因为程序可能会在已经安装了 .exe 的机器上运行,所以我不想费力手动查找 .exe。
  • 对我不起作用。如果我找到解决方案,我稍后会回到这个问题并自己回答。
  • 第二个例子有错误。 os.environ()['PATH'] 应替换为 os.environ['PATH']
  • @WyattBaldwin 谢谢,已修复。以后可以随意直接编辑答案。
  • env={'PATH': os.getenv('PATH')} 似乎没用(PATH 无论如何都是继承的),如果孩子可能需要其他环境变量,甚至有害。如果 OP 知道路径; OP 可以传递完整路径(包括文件扩展名)(在args[0] 中)。
【解决方案2】:

好的,这就是我的工作方式。

env = os.environ
proc = subprocess.Popen(args, env=env)

【讨论】:

  • 如果我没记错的话,这并没有实际效果,因为“[Popen 的默认行为是] 继承当前进程的环境”。
  • @WyattBaldwin:你没看错。很容易检查,运行:Popen([sys.executable, '-c', 'import os; print(os.environ)']),可以看到环境被继承了。如果要修改子环境,可能需要传递envenv=dict(os.environ, ENVVAR='visible in only in child')
【解决方案3】:

我自己也在为此苦苦挣扎,直到找到this python bug report

"如果您在 Windows 上将目录添加到 PATH 中,以便该目录包含在引号中,则子进程不会在其中找到可执行文件。"由于 Windows 不需要引号,因此删除它们可以解决我的问题(在 2.7 中)。

【讨论】:

  • 有趣 - 这也许可以解释为什么添加 shell=True 似乎经常可以解决这个问题。
【解决方案4】:

我的一位同事在 Windows 10 64 位上使用 Python 3.6.5 重现了这个问题。

然而,安装的 Python 版本是 32 位。

重新安装 64 位版本的 Python 解决了这个问题。

【讨论】:

    猜你喜欢
    • 2016-11-30
    • 2015-05-20
    • 2018-01-14
    • 1970-01-01
    • 2013-11-13
    • 2021-11-30
    • 2021-02-14
    • 2010-12-13
    • 2011-07-09
    相关资源
    最近更新 更多