无缓冲读取子进程的标准输出

Osc*_*car 7 node.js socket.io

我正在尝试读取Node.js启动的Python脚本的输出。但是,只有在过程完成后,我才能访问数据。

var proc, args;

args = [
    './bin/build_map.py',
    '--min_lon',
    opts.sw.lng,
    '--max_lon',
    opts.ne.lng,
    '--min_lat',
    opts.sw.lat,
    '--max_lat',
    opts.ne.lat,
    '--city',
    opts.city
];

proc = spawn('python', args);

proc.stdout.on('data', function (buf) {
    console.log(buf.toString());
    socket.emit('map-creation-response', buf.toString());
});
Run Code Online (Sandbox Code Playgroud)

如果使用{stdio:'inherit'}启动该过程,则可以直接在控制台中看到输出。但是做类似process.stdout.on('data',...)的事情是行不通的。

如何确保子进程到达时可以读取子进程的输出并将其定向到其他地方?

ctt*_*ctt 0

当进程由 生成时child_process.spawn(),连接到子进程的标准输出和标准错误的流实际上在 Nodejs 端没有缓冲。为了说明这一点,请考虑以下程序:

\n\n
const spawn = require(\'child_process\').spawn;\n\nvar proc = spawn(\'bash\', [\n  \'-c\',\n  \'for i in $(seq 1 80); do echo -n .; sleep 1; done\'\n]);\n\nproc.stdout\n.on(\'data\', function (b) {\n  process.stdout.write(b);\n})\n.on(\'close\', function () {\n  process.stdout.write("\\n");\n});\n
Run Code Online (Sandbox Code Playgroud)\n\n

该程序运行bash并在 80 秒内每秒发出.字符,同时通过事件消耗该子进程的标准输出data。您应该注意到 Node 程序每秒都会发出这些点,这有助于确认 Nodejs 端没有发生缓冲。

\n\n

另外,正如 Nodejs 文档中所解释的child_process

\n\n
\n

默认情况下,标准输入、标准输出和标准错误的管道是在父 Node.js 进程和生成的子进程之间建立的。可以通过这些管道以非阻塞方式传输数据。但请注意,有些程序在内部使用行缓冲 I/O。虽然这不会影响 Node.js,但这可能意味着发送到子进程的数据可能不会立即被消耗。

\n
\n\n

您可能想确认您的 Python 程序没有缓冲其输出。如果您觉得您正在将 Python 程序中的数据作为单独的不同写入发送到标准输出,请考虑sys.stdout.flush()在每次写入后运行,以建议 Python 应该实际写入数据而不是尝试缓冲数据。

\n\n

更新:在此提交中,Nodejs 文档中的段落已被删除,原因如下:

\n\n
\n

文档:删除有关子进程 stdio 的令人困惑的注释

\n\n

\xe2\x80\x99s 这段话要说什么并不明显。特别是,进程是否对其 stdio 流使用缓冲机制以及使用何种缓冲机制并不影响,一般来说,无法保证进程何时消耗发送给它的数据。

\n
\n\n

这表明在 Nodejs 进程接收数据之前可能存在缓冲。尽管如此,应注意确保 Nodejs 上游控制范围内的进程不会缓冲其输出。

\n