如何在 python3 中的 EOF 之前提前读取标准输入缓冲区?

How to read stdin buffer in advance before an EOF in python3?

在我的 python 代码中,我编写了以下函数来接收来自标准输入的自定义二进制包。

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)

我希望子进程在收到包后从其标准输入缓冲区中读取并给出输出。但它不起作用,我认为原因是子进程不会开始读取,除非它的标准输入缓冲区接收到信号,如 EOF。作为证明,如果我在 stdin.write 之后关闭 childProcess 的标准输入,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,然后按 ctrl d 在类 UNIX 环境中。它们为终端生成控制字符([=75= 上的代码 26],UNIX 上的代码 04)并由终端读取。终端(在阅读此代码后)将基本上停止写入程序 stdin 关闭 它。

在Python中,一个文件对象将永远.read()。 EOF条件是.read()returns''。在其他一些语言中,这可能是 -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 字节。

Python
class 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()
节点
childProcess = require('child_process').spawn('./python_code.py');
childProcess.stdin.write("Some text I want to send.");
childProcess.stdin.write(Buffer.from([00]));

您可能读错了长度

我认为您在 Len 中捕获的值小于文件的长度。

Python
import sys

while True:
    length = int(sys.stdin.read(2))
    with open("test.txt", "a") as f:
        f.write(sys.stdin.read(length))
节点
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");