一尘不染

Python- 从subprocess.communicate()读取流输入

python

我正在使用Python subprocess.communicate()从运行约一分钟的进程中读取stdout。

我该如何stdout以流方式打印出该流程的每一行,以便可以看到生成的输出,但仍然阻止该流程终止,然后再继续?

subprocess.communicate() 似乎一次给出所有输出。


阅读 4048

收藏
2020-02-07

共2个答案

一尘不染

这是一个简单的示例(不检查错误):

import subprocess
proc = subprocess.Popen('ls',
                       shell=True,
                       stdout=subprocess.PIPE,
                       )
while proc.poll() is None:
    output = proc.stdout.readline()
    print output,

如果ls结束太快,则while循环可能会在你读取所有数据之前结束。

你可以通过以下方式在stdout中捕获其余部分:

output = proc.communicate()[0]
print output,
2020-02-07
一尘不染

要在子进程刷新其stdout缓冲区后逐行获取子进程的输出:

#!/usr/bin/env python2
from subprocess import Popen, PIPE

p = Popen(["cmd", "arg1"], stdout=PIPE, bufsize=1)
with p.stdout:
    for line in iter(p.stdout.readline, b''):
        print line,
p.wait() # wait for the subprocess to exit

iter()用于在编写行后立即读取行,以解决Python 2中的预读错误。

如果子进程的stdout在非交互模式下使用块缓冲而不是行缓冲(这会导致输出延迟,直到子缓冲区已满或被子进程显式刷新),然后你可以尝试使用以下方式强制使用无缓冲输出 pexpect,pty模块或unbuffer,stdbuf,script公用事业,见问:为什么不直接使用管道(popen方法())?

这是Python 3代码:

#!/usr/bin/env python3
from subprocess import Popen, PIPE

with Popen(["cmd", "arg1"], stdout=PIPE, bufsize=1,
           universal_newlines=True) as p:
    for line in p.stdout:
        print(line, end='')

注意:与Python 2不同,Python 2照原样输出子进程的字节串。Python 3使用文本模式(使用locale.getpreferredencoding(False)编码对cmd的输出进行解码)。

2020-02-07