310

如何使用 获取运行进程的输出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'
>>> 
4

7 回答 7

308

如果您的 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为相同的结果。

如下所述,您可以在此其他答案中找到更详细的解释。

于 2012-01-02T11:45:57.813 回答
224

的输出subprocess.call()应该只重定向到文件。

你应该subprocess.Popen()改用。然后,您可以传递subprocess.PIPEstderr、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()方法。仅仅使用任何类似文件的对象都不会成功。

请参阅此处了解更多信息。

于 2010-01-03T22:13:40.523 回答
85

对于 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)
于 2016-01-19T09:44:30.413 回答
51

我有以下解决方案。它捕获执行的外部命令的退出代码、标准输出和标准错误:

import shlex
from subprocess import Popen, PIPE

def get_exitcode_stdout_stderr(cmd):
    """
    Execute the external command and get its exitcode, stdout and stderr.
    """
    args = shlex.split(cmd)

    proc = Popen(args, stdout=PIPE, stderr=PIPE)
    out, err = proc.communicate()
    exitcode = proc.returncode
    #
    return exitcode, out, err

cmd = "..."  # arbitrary external command, e.g. "python mytest.py"
exitcode, out, err = get_exitcode_stdout_stderr(cmd)

我在这里也有一篇关于它的博客文章。

编辑:解决方案已更新为不需要写入 temp 的较新解决方案。文件。

于 2014-01-08T15:50:06.080 回答
31

我最近才弄清楚如何做到这一点,这是我当前项目的一些示例代码:

#Getting the random picture.
#First find all pictures:
import shlex, subprocess
cmd = 'find ../Pictures/ -regex ".*\(JPG\|NEF\|jpg\)" '
#cmd = raw_input("shell:")
args = shlex.split(cmd)
output,error = subprocess.Popen(args,stdout = subprocess.PIPE, stderr= subprocess.PIPE).communicate()
#Another way to get output
#output = subprocess.Popen(args,stdout = subprocess.PIPE).stdout
ber = raw_input("search complete, display results?")
print output
#... and on to the selection process ...

您现在将命令的输出存储在变量“输出”中。“stdout = subprocess.PIPE”告诉类从 Popen 中创建一个名为“stdout”的文件对象。据我所知,communicate() 方法只是作为一种方便的方式来返回输出元组和您运行的进程的错误。此外,该过程在实例化 Popen 时运行。

于 2010-07-14T14:42:34.923 回答
24

关键是使用功能subprocess.check_output

例如,以下函数捕获进程的 stdout 和 stderr 并返回它们以及调用是否成功。它与 Python 2 和 3 兼容:

from subprocess import check_output, CalledProcessError, STDOUT

def system_call(command):
    """ 
    params:
        command: list of strings, ex. `["ls", "-l"]`
    returns: output, success
    """
    try:
        output = check_output(command, stderr=STDOUT).decode()
        success = True 
    except CalledProcessError as e:
        output = e.output.decode()
        success = False
    return output, success

output, success = system_call(["ls", "-l"])

如果要将命令作为字符串而不是数组传递,请使用此版本:

from subprocess import check_output, CalledProcessError, STDOUT
import shlex

def system_call(command):
    """ 
    params:
        command: string, ex. `"ls -l"`
    returns: output, success
    """
    command = shlex.split(command)
    try:
        output = check_output(command, stderr=STDOUT).decode()
        success = True 
    except CalledProcessError as e:
        output = e.output.decode()
        success = False
    return output, success

output, success = system_call("ls -l")
于 2017-11-06T20:08:42.523 回答
16

Ipython外壳中:

In [8]: import subprocess
In [9]: s=subprocess.check_output(["echo", "Hello World!"])
In [10]: s
Out[10]: 'Hello World!\n'

根据sargue的回答。归功于 sargue。

于 2015-09-05T13:14:48.190 回答