我正在运行这个简单的Python程序来合并两个子进程的输出行:
import select
from subprocess import PIPE, Popen
import sys
subprocs = [
Popen(cmdline, stdout=PIPE) for cmdline in
[['./repeat', 'abc'], ['./repeat', 'xyz']]
]
while True:
rstreams, _, _ = select.select([p.stdout for p in subprocs], [], [])
for stream in rstreams:
sys.stdout.buffer.write(stream.readline())
…其中repeat
是一个定期生成输出的简单脚本:
#!/bin/bash
while sleep 1 ; do echo $@ ; done
我希望将两个子流程的输出逐行合并,以便合并后的输出以任意顺序包含abc
和xyz
的行,并及时进行中继。 (不需要混合数据,例如abxyzc
。]
但是,我发现上面的Python程序很长时间没有产生任何输出,或者直到我按下Ctrl C为止。
((我曾尝试将stream.readline()
更改为stream.read(1)
,以防问题是readline()
挂起,即使我不希望这种交错,但也无济于事。在Python 3.5中会发生Linux上的.2和macOS上的Python 3.7.6。)
当子流程清楚地产生输出时,select()
为什么要等待?
sys.stdout.buffer
内部具有缓冲区,因此我们无法立即看到结果。 我们可以在写入后显式刷新结果。将sys.stdout.buffer.flush()
放在buffer.write()
之后。或者只使用print(stream.readline())
而不是sys.stdout.buffer
。