在Python中运行外部程序(可执行文件)?

122
我刚开始学习Python,并且一直在尝试从Python中运行外部可执行文件。
我有一个用Fortran编写的程序的可执行文件。假设可执行文件的名称是flow.exe,并且我的可执行文件位于C:\Documents and Settings\flow_model。我尝试了os.systempopen命令,但到目前为止,我无法使其工作。下面的代码似乎打开了命令窗口,但它不会执行模型。
# Import system modules
import sys, string, os, arcgisscripting
os.system("C:/Documents and Settings/flow_model/flow.exe")

怎么修复这个问题?

2
可能是在Python中调用外部命令的重复问题。 - mkobit
A) 不要使用没有人拥有的程序作为示例,而是使用每个人都有的程序,例如 C:\windows\system32\calc.exe 或 Chrome(位于 c:\program files..)。B) 如果您尝试从 cmd 控制台运行它(或者是 IDE 的终端,例如 VS Code 的终端)C:\blah>python blah.py<ENTER>,您会清楚地看到发生了什么。 'C:/Documents' 不被识别为内部或外部命令、可执行程序或批处理文件。 - barlop
15个回答

56

如果使用Python 2.7或更高版本(尤其是Python 3.5之前),您可以使用以下代码:

import subprocess
  • subprocess.call(args, *, stdin=None, stdout=None, stderr=None, shell=False)函数运行由args描述的命令。等待命令完成,然后返回returncode属性。
  • subprocess.check_call(args, *, stdin=None, stdout=None, stderr=None, shell=False)函数带参数运行命令。等待命令完成。如果返回代码为零,则返回;否则引发CalledProcessError。CalledProcessError对象将在returncode属性中具有返回代码。

示例:subprocess.check_call([r"C:\pathToYourProgram\yourProgram.exe", "your", "arguments", "comma", "separated"])

在常规Python字符串中,\U字符组合表示扩展的Unicode代码点转义。

这是文档链接:http://docs.python.org/3.2/library/subprocess.html

对于Python 3.5+,现在可以在许多情况下使用run()函数:https://docs.python.org/3.5/library/subprocess.html#subprocess.run


8
Python 3.6.3 推荐使用 run() - Ricardo Zorio

49

最简单的方法是:

import os
os.startfile("C:\Documents and Settings\flow_model\flow.exe")

它有效;我试过了。


2
程序正常运行,但是否有办法添加像-start等参数? - Bassem Shahin
3
无法工作:module 'os' has no attribute 'startfile'。(使用python3.6) - not2qubit
显然,与文档所给的印象相反,它在任何Windows相关的东西上都不起作用。 - not2qubit

48

那些空格确实会带来麻烦。尝试使用相对路径和os.systemsubprocess等方法,以及在os.chdir('C:/Documents\ and\ Settings/')之后使用相对路径。

如果尝试规避路径中的空格问题失败了,那么我的下一个最佳建议是避免在关键路径中使用空格。你能否创建一个没有空格的目录,将关键的.exe文件复制到该目录中,然后尝试这样做呢?这些毁灭性的空格对你的健康绝对是必要的吗?


1
Alex,谢谢。这个也有效。如果您不介意,我还有一个问题。 如果我的可执行文件要求输入文件的名称怎么办?我尝试使用stdin,但迄今为止没有成功。 - Mesut
2
@mesut,那个可执行文件是用什么来“请求”文件名的?如果它使用自己的标准输入,例如,你可以尝试使用subprocess.Popen将你想要的值传递给它。如果它更深层次地使用了“控制台”输入,可以尝试使用wexpect,网址为http://sage.math.washington.edu/home/goreckc/sage/wexpect/。 - Alex Martelli
现在的代码会从cmd窗口打开exe文件,然后可执行文件会要求输入文件名。有没有办法可以在代码中定义这个名称(可能作为路径)?我尝试了subprocess.popen,并查看了变量。我以为我可以使用stdin,但并没有真正起作用。如果您可以给我一个位于C:\flow_model的可执行文件名称为flow.exe、输入文件名称为sac_bsl.txt的示例子,我将不胜感激。 - Mesut
“询问输入文件名”的部分是麻烦的。正如我之前提到的,由于不知道该exe的编码方式,因此“wexpect”是最可行的解决方案,因为它可以让您模拟在cmd窗口调用该exe文件时所看到的情况。 - Alex Martelli

30

如果我是你,我会在路径前面插入一个 'r',表示它是原始字符串 - 然后你就不必使用正斜杠了。例如:

os.system(r"C:\Documents and Settings\flow_model\flow.exe")

这里的主要问题是内部的空格,您的建议很好,但没有解决主要问题。 - Frediano Ziglio
@FredianoZiglio 你的意思是他的建议行不通? - barlop

23

你的使用方法是正确的。我猜测你的外部程序 flow.exe 需要在其所在目录中执行,因为它需要访问存储在那里的某些外部文件。

所以你可以尝试:

import sys, string, os, arcgisscripting
os.chdir('c:\\documents and settings\\flow_model')
os.system('"C:\\Documents and Settings\\flow_model\\flow.exe"')

(注意单引号内的双引号...)


完美运行,如何直接将结果存储到数据框中? - Sade
@Sade,你不是原帖作者。这个解决方案对原帖作者无效! - barlop
这个不行:os.chdir('C:\\Program Files (x86)\\Google\\Chrome\\Application')os.system('C:\\Program Files (x86)\\Google\\Chrome\\Application\chrome.exe'),然后会出现 'C:\Program' 不是内部或外部命令,也不是可运行的程序或批处理文件。 - barlop
@barlop 1) 感谢您恢复一个13年前的帖子 2) 你也不是原帖作者,你的评论毫无用处 3) “在单引号内注意双引号”这个提示的哪一部分让你不理解了?解决方案已经非常明确地说明了,但你却没有正确实施它,然后抱怨它不起作用……所以请先学会阅读,再发表任何无意义的评论! - Adrien Plisson
@AdrienPlisson 我错过了你在引号方面的处理方式...我现在看到它可以在单引号内使用双引号。至于你的警告声明...如果你写成“Be aware of”,那会更清晰。因为“Beware”往往是指不要做某件事情。例如,一个人会说“Beware of the unhealthy cake”。但是不会说“Beware of the healthy food”。而且你可以指出需要注意的事项所在...以及它的必要性。“请注意在os.system命令中使用单引号包围双引号的必要性”。 - barlop

12

使用 subprocess 模块,它是一个较小的模块,所以可以更快地运行 .exe 文件。

import subprocess
subprocess.Popen([r"U:\Year 8\kerbal space program\KSP.exe"])

2
你的意思是它能更快地启动 .exe 文件? - Peter Mortensen
OSError: [WinError 740] 请求操作需要提升权限 - lloydyu24

9
通过使用 os.system
import os
os.system(r'"C:/Documents and Settings/flow_model/flow.exe"')

3
如果是我,我会把EXE文件放在根目录(C:)中,看看是否可以这样工作。如果可以,很可能是目录名称中的空格(已经提到)。如果不行,可能是一些环境变量。
此外,请尝试检查您的stderr(使用int3先前的答案)。
import subprocess
process = subprocess.Popen(["C:/Documents and Settings/flow_model/flow.exe"], \
                           stderr = subprocess.PIPE)
if process.stderr:
    print process.stderr.readlines()

由于我通常不使用Popen或Windows,所以代码可能不完全正确,但应该可以理解。可能会发现错误消息在错误流中。


3
import os
path = "C:/Documents and Settings/flow_model/"
os.chdir(path)
os.system("flow.exe")

备注:由barlop添加

一位评论者问为什么这样可以,下面是原因。

问题在于os.system("...")在路径中有空格时无法正常工作。(注意os.system可以使用('"...."')但无论如何)

如果OP尝试从cmd提示符运行程序,他们会清楚地看到错误。

    C:\carp>type blah.py
    import  os
    os.system(R"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe")
    
    C:\carp>python blah.py
    'C:\Program' is not recognized as an internal or external command,
    operable program or batch file.
    
    C:\carp>

所以对于os.system("calc.exe")来说是可以的(因为calc.exe在路径环境变量中),或者对于os.system(R"c:\windows\system32\calc.exe")也是可以的。那个路径中没有空格。

C:\>md "aa bb cc"

C:\>copy c:\windows\system32\calc.exe "c:\aa bb cc\cccalc.exe"
        1 file(s) copied.

这个可以工作(假设文件路径为"c:\aa bb cc\cccalc.exe")

import  os 
os.chdir(R"c:\aa bb cc")
os.system("cccalc.exe")

其他选项包括subprocess.run和subprocess.popen。


1
请添加一个解释,说明你的代码如何解决这个问题。 - rje
这篇文章基本上将执行的*.exe文件视为使用Windows *.bat文件一样处理。 - SamAct
@SamAct 不,那是胡言乱语。 - barlop
@rje 我在他的解答基础上添加了一些说明,阐述为什么他的解决方案可行。 - barlop

3

尝试

import subprocess
subprocess.call(["C:/Documents and Settings/flow_model/flow.exe"])

尝试过了,结果还是一样。似乎它打开了cmd窗口,但是却无法运行可执行文件。我单独尝试了可执行文件,它可以正常工作。我还将文件夹移动到C:/flow_model。但是没有任何改变。 - Mesut

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接