使用Python运行其他程序

8 投票
4 回答
13620 浏览
提问于 2025-04-15 19:36

我有一个命令,在命令行上运行得很好。这个命令有很多参数,比如 cmd --thing foo --stuff bar -a b input output

我想从 Python 里运行这个命令,并且希望它在完成之前一直等待。这个脚本在输出信息到 stdoutstderr 时,我希望这些信息能立刻显示给用户。

我该用哪个模块呢?

我试过:


import commands
output = commands.getoutput("cmd --thing foo --stuff bar -a b input output")
print output

这个方法很好用,但 stdout 的输出要等到最后才返回。


import os
os.system("cmd --thing foo --stuff bar -a b input output")

这个方法在命令真正完成时才会打印所有输出。


import subprocess
subprocess.call(["cmd", "--thing foo", "--stuff bar", "-a b", "input", "output"])

这个方法好像没有正确传递参数(我还没找到具体的问题,但 cmd 拒绝了我的输入)。如果我把 echo 放在第一个参数,它会打印出这个命令,而直接在终端里粘贴这个命令是完全可以正常工作的。


import subprocess
subprocess.call("cmd --thing foo --stuff bar -a b input output")

和上面的一样。

4 个回答

2

使用 commands.getstatusoutput() 这个方法不行吗?我觉得它会立刻给你返回状态信息。

7

你需要把每个字段单独用引号括起来,也就是说,要把选项和它们的参数分开。

import subprocess
output = subprocess.call(["cmd", "--thing", "foo", "--stuff", "bar", "-a", "b", "input", "output"])

否则你实际上是在这样运行命令

$ cmd --thing\ foo --stuff\ bar -a\ b input output

为了把输出放入管道中,你需要稍微改变一下调用方式

import subprocess
output = subprocess.Popen(["cmd", "--thing", "foo", "--stuff", "bar", "-a", "b", "input", "output"],stdout=subprocess.PIPE)
output.stdout   #  <open file '<fdopen>', mode 'rb'>
4

如果你不需要在代码中处理输出,只是想把它展示给用户(从你的问题来看,这点不是很明确,似乎你自己回答的时候也是这么想的),最简单的方法就是:

rc = subprocess.call(
    ["cmd", "--thing", "foo", "--stuff", "bar", 
     "-a", "b", "input", "output"])
print "Return code was", rc

也就是说,尽量不要使用管道——让标准输出和错误输出直接在终端上显示。这样可以避免缓冲的问题。一旦你使用了管道,缓冲通常会成为一个问题,特别是当你想实时显示输出的时候(我很惊讶你自己回答的时候没有遇到这个问题;-)。

顺便提一下,如果你想同时显示和捕获输出,我总是推荐使用 pexpect(在Windows上用 wexpect),这正好可以解决缓冲的问题。

撰写回答