【问题标题】:Python: Capture stdout from subprocess.callPython:从 subprocess.call 中捕获标准输出
【发布时间】:2017-03-07 18:19:30
【问题描述】:

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

  • 捕获标准输出并在发生时打印它
  • 将stdout作为一个整体捕获并在cmd完成时对其进行处理

我查看了subprocess.check_output,但它没有允许我在输出发生时打印输出的标准输出参数。

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

from subprocess import Popen, PIPE

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

print(stdout, stderr)

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

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

我似乎仍然无法将输出重定向到标准输出和命令完成时可以解析的某种缓冲区。

理想情况下,我想要这样的东西:

# 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)

有没有推荐的方法来完成这个?

【问题讨论】:

标签: python


【解决方案1】:

您使用给 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

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

【讨论】:

    【解决方案2】:
    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()
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-07-09
      • 1970-01-01
      • 1970-01-01
      • 2011-07-05
      • 2013-05-10
      • 2011-11-28
      • 1970-01-01
      相关资源
      最近更新 更多