Node.js调用Python子进程时input后接sys.stdin.buffer.read无法终止读stdin问题
问题根因
你猜测的冲突确实存在,核心是Python的文本IO接口和二进制IO接口共用输入缓冲区时的预读机制导致的:input()是文本模式的stdin接口,调用时会预读尽可能多的数据到内部文本缓冲区(不止读至换行符),你后续要读取的二进制数据有部分/全部被提前预读到了文本缓冲区,sys.stdin.buffer.read()直接读取原始标准输入缓冲区时就拿不到足够的size字节,因此会永久阻塞等待数据。
解决方案
方案1:统一使用二进制IO读取(兼容原有换行分隔长度的逻辑)
完全放弃文本接口input(),所有读取操作都走sys.stdin.buffer,避免预读冲突:
# Python 侧修改后代码 import sys # 逐字节读取长度直到遇到换行符 size_byte = b'' while True: cur = sys.stdin.buffer.read(1) if cur == b'\n': break size_byte += cur size = int(size_byte.decode().strip()) # 读取指定长度的二进制数据 data = sys.stdin.buffer.read(size)
Node侧代码无需修改。
方案2:固定字节长度传大小(更稳定,推荐二进制通信场景使用)
避免用文本换行做分隔符,直接发送固定4字节的大端整数表示后续二进制数据长度,无需处理字符串编解码和换行识别,稳定性更高:
// Node.js 侧修改后代码 const python_command = command.serializeBinary() const python = spawn('test/production_tests/py_test_scripts/protocolbuffer/venv/bin/python', ['test/production_tests/py_test_scripts/protocolbuffer/command_handler.py']); const bufferSize = python_command.byteLength // 写入4字节无符号大端整数表示数据长度 const lenBuf = Buffer.alloc(4) lenBuf.writeUInt32BE(bufferSize) python.stdin.write(lenBuf) python.stdin.write(python_command) // 如果是单次通信不需要后续写入,可主动调用end触发EOF // python.stdin.end()
# Python 侧对应代码 import sys import struct # 读取4字节解析为长度 size = struct.unpack('>I', sys.stdin.buffer.read(4))[0] data = sys.stdin.buffer.read(size)
内容的提问来源于stack exchange,提问作者ibrahim koz
相关产品推荐
相关产品推荐

