Python:从subprocess.call捕获标准输出

时间:2017-03-07 18:19:31

标签: python

我在使用Python执行shell cmd时尝试做两件事:

  • 捕获标准输出并在发生时将其打印
  • 整体捕获标准输出并在cmd完成时处理它

我查看了subprocess.check_output,但它没有stdout参数,可以让我在输出时打印输出。

所以在阅读this question之后,我意识到我可能需要尝试不同的方法。

from subprocess import Popen, PIPE

process = Popen(task_cmd, stdout = PIPE)
stdout, stderr = process.communicate()

print(stdout, stderr)

这种方法的问题在于根据文档Popen.communicate()

  

从stdout和stderr读取数据,直到达到文件结尾。   等待进程终止

我似乎仍然无法将输出重定向到stdout AND到某种缓冲区,可以在命令完成时解析。

理想情况下,我喜欢以下内容:

# captures the process output and dumps it to stdout in realtime
stdout_capture = Something(prints_to_stdout = True)
process = Popen(task_cmd, stdout = stdout_capture)

# prints the entire output of the executed process
print(stdout_capture.complete_capture)

是否有推荐的方法来实现这一目标?

2 个答案:

答案 0 :(得分:0)

使用赋予Popen stdout=PIPE的方法是正确的,但是不能使用.communicate(),因为它会在执行后返回值。相反,我建议您阅读.stdout

获取输出的唯一保证方法是一次从管道读取一个字符。这是我的方法:

def passthrough_and_capture_output(args):
    import sys
    import subprocess

    process = subprocess.Popen(args, stdout=subprocess.PIPE, universal_newlines=True)
    # universal_newlines means that the output of the process will be interpreted as text
    capture = ""

    s = process.stdout.read(1)
    while len(s) > 0:
        sys.stdout.write(s)
        sys.stdout.flush()
        capture += s
        s = process.stdout.read(1)

    return capture

请注意,一次读取一个字符会产生大量开销,因此,如果您稍稍落后一点,我建议您用不同数量的字符替换1中的read(1)批量输出。

答案 1 :(得分:-1)

from subprocess import check_output, CalledProcessError

def shell_command(args):
    try:
        res = check_output(args).decode()
    except CalledProcessError as e:
        res = e.output.decode()
    for r in ['\r', '\n\n']:
        res = res.replace(r, '')
    return res.strip()
相关问题