Python3 print stdout flush 未被 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 代码按预期运行,表明刷新确实触发了 stdout 数据侦听器,从而给出

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

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

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

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

这是因为

,在Python中,刷新在下一次打印并写入stdout缓冲区之前没有完成吗?

是的。

嗯,这是读者效应,而不是作家效应。 你当然不能指望读者看到时间诱导 使用不雅的代码记录边界,就像您发布的那样。

您有一个连接子项和父项的管道。

子写入缓冲'0n', 调用写入(2(, 然后继续前进。 节点在 I/O 上被阻塞,正在等待空管道。 write(2( 解封节点, 它至少消耗两个字节。 然而,在另一个核心上,孩子一直在忙着发出两个字节 编写并安排被阻止的读者变得可安排。 这涉及的工作很少。 父母很有可能还没有处理完 子字节写入其第六个字节时的前两个字节。 因此,父级读取包含多行的批处理块。

父母至少有两种方法可以与孩子同步。 孩子可以承诺总是写一个换行符分隔 记录,就像这里一样。然后父母只会读到 处理新可用记录时的分隔符。 或者孩子可以承诺写(n,buf(对,其中n告诉 我们的缓冲区正好有那么多字节。 再次,父将进行面向记录的读取。

最新更新