Python3 打印 stdout flush 未被 Node.js subprocess.stdout 获取

Python3 print stdout flush not picked up by Node.js subprocess.stdout

据我了解,subprocess.stdout.on('data', ...) 每次刷新标准输出时都会触发。

我有以下 NodeJS 代码:

const cp = require('child_process');

const subprocess = cp.spawn(`python3`, [`main.py`]);

subprocess.stdout.on(`data`, (data) => {
    console.log(`Got: ${data.toString()}`)
})

在同一文件夹中,main.py 包含:

import time

for i in range(5):
    print(i, flush=True)
    # time.sleep(1)

如果 time.sleep(1) 行未注释,NodeJS 代码按预期运行,表明 flush 确实触发了 stdout 数据监听器,给出

Got: 0
Got: 1
Got: 2
Got: 3
Got: 4

但是,当注释该行时,行为不一致,监听器触发 once/twice 而不是四次。

这是因为在 Python 中,刷新在下一次打印到来并写入标准输出缓冲区之前没有完成吗?

(上下文:我正在使用它来监听 Python 程序的进度(通过 stdout),但我的刷新没有被拾取)

Is this because, in Python, the flushing did not complete before the next print comes and writes to the stdout buffer?

是的。

嗯,这是 reader 效果,而不是作家效果。 你当然不能指望 reader 看到 timing-induced 用像你发布的那样的活泼代码记录边界。

您有一条管道将 child 连接到 parent。

Child 写入缓冲的 '0\n', 调用写入(2), 并继续前进。 节点在 I/O 上被阻塞,等待空管道。 write(2) 解锁节点,它消耗 至少 两个字节。 但是,在另一个核心上,child 一直忙于发布 two-byte 写入并安排阻塞的 readers 变得可调度。 这涉及很少的工作。 parent 很有可能还没有处理完 child 写入第六字节时的前两个字节。 因此 parent 读取包含多行的批处理块。

parent 至少有两种方法可以与 child 同步。 child 可以 承诺 总是写一个 newline-delimited 像这里一样记录下来。然后 parent 只会读取到 处理新可用记录时的定界符。 或者 child 可以承诺写入 (n, buf) 对,其中 n 告诉 我们的缓冲区恰好有那么多字节。 再次 parent 会进行 record-oriented 读取。