无缓冲子进程输出(最后一行缺失)
我可能忽略了一些非常明显的东西。我需要运行一个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,所以它应该是没有缓存的。我也尝试过在C代码退出前加上fflush(stdout),但似乎在程序退出前完全没有必要刷新输出流。
有没有人有什么想法?
2 个回答
3
问题在于,你一直在读取输出的每一行,直到这个进程结束(通过process.poll()
来检查)。不过,由于你使用了一个特定的选项,实际上是有缓存的。
你需要继续读取进程的标准输出,直到到达文件的末尾或者遇到空行为止。
2
readline()
这个函数需要先把文本缓存起来,等到遇到换行符才会处理。
你总是会遇到竞争条件——无论你用多少不带缓存的流,都无法解决这样一个问题:你在处理一行数据,然后检查是否退出,再读取一行数据。如果在你处理这一行的时候,子进程已经退出了,那你就不会再读取到其他内容了。而且,命令行本身可能也在引入自己的缓存。
所以你可以选择:
使用
communicate()
,这样在子进程运行时就不会有详细的输出。确保在进程退出后继续读取,直到你遇到文件结束符(EOF)。
我还建议你修改代码,这样就不需要使用 shell=True
。