使用Python中的subprocess进行进程的非缓冲读取

24

我正在尝试从一个产生长时间且耗时输出的进程中读取信息。然而,我希望在其输出生成时就能捕获它。但是使用以下代码似乎会缓存命令的输出,使得我最终一次性获取所有输出行:

p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, bufsize=0)
    for line in p.stdout:
        print line

我正在尝试在MacOS 10.5上做这件事


请返回翻译后的文本:重复:https://dev59.com/B3NA5IYBdhLWcg3wrPyq,https://dev59.com/UnRB5IYBdhLWcg3wv5o_ - S.Lott
3个回答

29
文件迭代器正在进行一些内部缓冲处理。请尝试以下代码:

The file iterator is doing some internal buffering on its own. Try this:

line = p.stdout.readline()
while line:
    print line
    line = p.stdout.readline()

你还需要确保运行的进程实际上经常刷新其输出缓冲区。


谢谢,你帮我省去了一些抓狂的时间。 - haridsv
你还需要确保正在运行的进程实际上经常刷新其输出缓冲区。我调试了半天才发现,当stdout被重定向到管道时,它有一个相当大的缓冲区。所以我不得不在程序代码中添加一些刷新来使输出实际上出现。 - Calmarius

6
通常,每个程序都会对其输入和/或输出通道进行比您所需的更多的缓冲...除非它被欺骗认为该通道实际上是终端!为了达到这个“善意欺骗”的目的,请使用pexpect - 它在Mac上运行得很好(在Windows上生活要困难得多,但有一些解决方案可能会有所帮助 - 幸运的是,由于您使用的是Mac,我们不需要深入探讨这些问题)。

3

4
在Python 2.7中,for line in p.stdout仍会延迟输出,而for line in iter(p.stdout.readline, b'')则按预期工作(它会在可用时立即产生行)。 - jfs
抱歉,2.x 版本不会默认使用新的 io 库,因为 Bug 报告上的最后一条评论已经说明了;你需要像这样做:for line in io.open(p.stdin.fileno()) - Ari
1
@Ari:这应该是for line in io.open(p.stdout.fileno())吗? - Richard Cook

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接