在我的Python代码中,我编写了以下函数来从stdin接收自定义的二进制包。
def recvPkg():
## The first 4 bytes stands for the remaining package length
Len = int.from_bytes(sys.stdin.buffer.read(4), byteorder='big', signed=True)
## Then read the remaining package
data = json.loads(str(sys.stdin.buffer.read(Len), 'utf-8'))
## do something...
while True:
recvPkg()
然后,在另一个 Node.js 程序中,我生成这个 python 程序作为子进程,并向其发送字节。
childProcess = require('child_process').spawn('./python_code.py');
childProcess.stdin.write(someBinaryPackage)
我希望子进程在收到包后从其标准输入缓冲区中读取并给出输出。但它不起作用,我认为原因是子进程不会开始读取,除非它的 stdin 缓冲区接收到信号,例如 EOF。作为证明,如果我在 stdin.write 之后关闭 childProcess 的 stdin,Python 代码将工作并立即接收所有缓冲的包。这不是我想要的方式,因为我需要打开 childProcess 的标准输入。那么node.js还有其他方法可以向childProcess发送信号以通知从stdin缓冲区读取数据吗?
(抱歉英语不好。
最佳答案
来自维基百科(强调我的):
Input from a terminal never really "ends" (unless the device is disconnected), but it is useful to enter more than one "file" into a terminal, so a key sequence is reserved to indicate end of input. In UNIX the translation of the keystroke to EOF is performed by the terminal driver, so a program does not need to distinguish terminals from other input files.
无法按照您期望的方式发送 EOF
字符。 EOF
并不是真正存在的字符。当您在终端中时,您可以按 Windows 上的按键序列 ctrlz 和 ctrld在类 UNIX 环境中。它们为终端生成控制字符(Windows 上的代码 26,UNIX 上的代码 04)并由终端读取。终端(在读取此代码后)将基本上停止写入程序 stdin
并关闭它。
在Python中,文件对象将永远.read()
。 EOF 条件是 .read()
返回 ''
。在某些其他语言中,这可能是 -1
或其他一些条件。
考虑:
>>> my_file = open("file.txt", "r")
>>> my_file.read()
'This is a test file'
>>> my_file.read()
''
这里的最后一个字符不是EOF
,那里什么也没有。 Python 的 .read()
直到文件末尾,并且不能再 .read()
了。
因为 stdin
在特殊类型的"file"中它没有结尾。 你必须定义那个目的。终端已将这一端定义为控制字符,但在这里您不会通过终端将数据传递到 stdin
,您必须自己管理它。
只需关闭文件
Input [...] never really "ends" (unless the device is disconnected)
关闭 stdin
可能是最简单的解决方案。 stdin
是一个无限文件,因此一旦写入完毕,只需将其关闭即可。
期待你自己的控制角色
另一个选项是定义您自己的控制字符。你可以在这里使用任何你想要的东西。下面的示例使用 NULL 字节。
Pythonclass FileWithEOF:
def __init__(self, file_obj):
self.file = file_obj
self.value = bytes()
def __enter__(self):
return self
def __exit__(self, *args, **kwargs):
pass
def read(self):
while True:
val = self.file.buffer.read(1)
if val == b"\x00":
break
self.value += val
return self.value
data = FileWithEOF(sys.stdin).read()
Node
childProcess = require('child_process').spawn('./python_code.py');
childProcess.stdin.write("Some text I want to send.");
childProcess.stdin.write(Buffer.from([00]));
您可能读到了错误的长度
我认为您在 Len
中捕获的值小于文件的长度。
import sys
while True:
length = int(sys.stdin.read(2))
with open("test.txt", "a") as f:
f.write(sys.stdin.read(length))
Node
childProcess = require('child_process').spawn('./test.py');
// Python reads the first 2 characters (`.read(2)`)
childProcess.stdin.write("10");
// Python reads 9 characters, but does nothing because it's
// expecting 10. `stdin` is still capable of producing bytes from
// Pythons point of view.
childProcess.stdin.write("123456789");
// Writing the final byte hits 10 characters, and the contents
// are written to `test.txt`.
childProcess.stdin.write("A");
关于python - 如何在python3中的EOF之前提前读取stdin缓冲区?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53102515/