Python Subprocess.call或Subprocess.Popen无法使用路径(Linux/Windows)中的可执行文件

Python Subprocess.call或Subprocess.Popen无法使用路径(Linux/Windows)中的可执行文件,python,windows,shell,subprocess,Python,Windows,Shell,Subprocess,我正在编写一个程序,需要在Linux和Windows上运行,并使用路径中存在的可执行文件(带参数)。(假定) 目前,我在windows中使用Subprocess.Call和Subprocess.Popen运行可执行文件时遇到问题 对于这样的代码,在windows 8中 def makeBlastDB(inFile, inputType, dbType, title, outDir): strProg = 'makeblastdb' strInput = '-in ' + inFi

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

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

对于这样的代码,在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环境变量中,我如何运行该命令?谢谢

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

proc = subprocess.Popen(args, env={'PATH': '/some/path'})
或者从系统环境变量继承
PATH
,而不必从系统环境中插入其他所有内容:

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

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

好的,下面是我如何让它工作的

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

我自己也在挣扎,直到我发现


“如果在Windows上将目录添加到PATH中,使目录以引号括起来,则子进程在其中找不到可执行文件。”由于Windows不需要引号,因此删除引号可以修复我的问题(在2.7中)。

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

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


重新安装64位版本的Python修复了此问题。

只需编写一个简单的脚本,将可执行文件添加到路径中,或者您可以提供可执行文件的完整路径。我不想这样做,因为可执行文件是第三方的,这意味着它可以安装在任何地方。它在shell中工作吗?你有没有比较过
echo%PATH%
os.environ['PATH']
?@J.F.Sebastian这个问题已经问了3年多了,OP已经以某种方式解决了他们的问题(答案可疑),我不确定你会从这里得到更多信息……;)这可能是一个不同的cwd,也可能是一些糟糕的windows怪癖,因为公认的答案没有多大意义。@wim:如果OP不更新这个问题,那么它应该被关闭为不可复制(因为显然
subprocess.Popen
可以运行(至少一些)Linux和windows上路径中的可执行文件)。谢谢。至于绝对路径,因为程序可能会在已经安装了.exe的机器上运行,所以我不想费事手动查找.exe。对我来说不起作用。如果我找到了解决方案,我会稍后再回答这个问题。第二个例子中有一个错误
os.environ()['PATH']
应替换为
os.environ['PATH']
@WyattBaldwin谢谢,已修复。以后您可以自己直接编辑答案。
env={'PATH':os.getenv('PATH')}
似乎没有用(路径还是继承的),甚至在孩子可能需要其他环境变量时有害。如果OP知道路径;OP可以传递完整路径(包括文件扩展名)(在
args[0]
中)。如果我没有弄错的话,这不会产生任何净效果,因为“Popen的默认行为是]继承当前进程的环境”。@WyattBaldwin:你没有弄错。很容易检查、运行:
Popen([sys.executable,'-c',import os;print(os.environ)'))
,以查看环境是否被继承。如果要修改子环境,您可能需要传递
env
env=dict(os.environ,ENVVAR='visible in only in child')
有趣-这可能解释了为什么添加shell=True似乎常常能解决此问题。