无缓冲的子进程输出(缺少最后一行)

时间:2010-03-12 12:10:15

标签: python subprocess popen

我必须忽略一些非常明显的东西。我需要执行一个C程序,实时显示它的输出,最后解析它的最后一行,这应该是直截了当的,因为打印的最后一行总是相同。

process = subprocess.Popen(args, shell = True,  
                           stdout = subprocess.PIPE, stderr = subprocess.PIPE)

# None indicates that the process hasn't terminated yet.
while process.poll() is None:

    # Always save the last non-emtpy line that was output by the child
    # process, as it will write an empty line when closing its stdout.
    out = process.stdout.readline()
    if out:
        last_non_empty_line = out

    if verbose:
        sys.stdout.write(out)   
        sys.stdout.flush()

# Parse 'out' here...

然而,偶尔会打印最后一行。 Popens的 bufsize 的默认值为0,因此它应该是无缓冲的。我还尝试在退出之前将 fflush(stdout)添加到C代码,但似乎在退出程序之前绝对不需要刷新流。

想点什么?

2 个答案:

答案 0 :(得分:3)

问题是你正在读取行,直到进程退出,(process.poll())而你因为shell标志而使用缓冲。

你必须继续阅读process.stdout,直到你到达文件末尾或空行。

答案 1 :(得分:2)

readline()必须缓冲文本,等待换行。

你总是会有一个竞争条件 - 没有任何数量的未缓冲流将处理你正在处理一条线,然后检查退出,然后读取一条线的事实,所以如果子进程退出而你是处理一条线,你不会读任何其他东西。另外,shell可能会引入自己的缓冲。

所以你可以:

  1. 使用communicate()并在子进程运行时放弃详细输出。

  2. 请确保您在退出流程后继续阅读,直至获得EOF。

  3. 我还建议您更改代码,这样就不必使用shell=True