获取subprocess.call()的输出
我该如何获取通过 subprocess.call()
运行的进程的输出呢?
如果把一个 StringIO.StringIO
对象传给 stdout
,会出现这个错误:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/subprocess.py", line 444, in call
return Popen(*popenargs, **kwargs).wait()
File "/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/subprocess.py", line 588, in __init__
errread, errwrite) = self._get_handles(stdin, stdout, stderr)
File "/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/subprocess.py", line 945, in _get_handles
c2pwrite = stdout.fileno()
AttributeError: StringIO instance has no attribute 'fileno'
7 个回答
105
对于Python 3.5或更高版本,建议使用subprocess模块中的run函数。这个函数会返回一个CompletedProcess
对象,你可以很方便地从中获取输出结果和返回代码。
from subprocess import PIPE, run
command = ['echo', 'hello']
result = run(command, stdout=PIPE, stderr=PIPE, universal_newlines=True)
print(result.returncode, result.stdout, result.stderr)
341
如果你使用的是Python 2.7或更高版本,可以用subprocess.check_output
这个功能,它基本上就是你想要的(它会把标准输出作为字符串返回)。
这里有个简单的例子(适用于Linux系统;请注意):
import subprocess
print subprocess.check_output(["ping", "-c", "1", "8.8.8.8"])
注意,ping命令在这里用的是Linux的写法(-c
表示计数)。如果你在Windows上试这个,记得把它改成-n
,这样才能得到相同的结果。
正如下面的评论所说,你可以在这个其他回答中找到更详细的解释。
236
从 subprocess.call()
得到的输出只能重定向到文件中。
你应该使用 subprocess.Popen()
来代替。这样你可以把 subprocess.PIPE
传给 stderr、stdout 和/或 stdin 参数,然后通过 communicate()
方法从管道中读取数据:
from subprocess import Popen, PIPE
p = Popen(['program', 'arg1'], stdin=PIPE, stdout=PIPE, stderr=PIPE)
output, err = p.communicate(b"input data that is passed to subprocess' stdin")
rc = p.returncode
这样做的原因是,subprocess.call()
使用的文件样对象必须有一个真实的文件描述符,因此需要实现 fileno()
方法。仅仅使用任何文件样的对象是无法达到这个效果的。
想了解更多信息,可以查看 这里。