Python 的 select() 延迟报告子进程输出的存在
Python's select() delays reporting presence of output from subprocesses
我是 运行 这个简单的 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 程序很长时间没有输出,或者直到我按下 CtrlC.
(我已经尝试将 stream.readline()
更改为 stream.read(1)
,以防 readline()
挂起时出现问题,尽管我不想要那种交错,但它没有帮助。发生在 Python 3.5.2 on Linux 和 Python 3.7.6 on macOS.)
为什么 select()
等待,而子进程显然正在生成输出?
根本原因是您使用了sys.stdout.buffer
,它内部有一个缓冲区,因此我们无法立即看到结果。
我们可以在写入后显式刷新结果。将 sys.stdout.buffer.flush()
放在 buffer.write()
之后。或者只使用 print(stream.readline())
而不是 sys.stdout.buffer
.
我是 运行 这个简单的 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 程序很长时间没有输出,或者直到我按下 CtrlC.
(我已经尝试将 stream.readline()
更改为 stream.read(1)
,以防 readline()
挂起时出现问题,尽管我不想要那种交错,但它没有帮助。发生在 Python 3.5.2 on Linux 和 Python 3.7.6 on macOS.)
为什么 select()
等待,而子进程显然正在生成输出?
根本原因是您使用了sys.stdout.buffer
,它内部有一个缓冲区,因此我们无法立即看到结果。
我们可以在写入后显式刷新结果。将 sys.stdout.buffer.flush()
放在 buffer.write()
之后。或者只使用 print(stream.readline())
而不是 sys.stdout.buffer
.