python - 如何在python3中的EOF之前提前读取stdin缓冲区?

标签 python node.js stdin

在我的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 上的按键序列 ctrlzctrld在类 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 字节。

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()
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 中捕获的值小于文件的长度。

Python
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/

相关文章:

python - 在嵌套列表中拆分字符串

python - 在 Python 中存储大文件的最快方法

javascript - 在express中传递额外参数 - Node.JS

node.js - React Native + Firebase + Expo 版本三角问题

c - 如何为另一个使用 stdin 输入的函数编写测试函数?

python - python 中类似 switch-case 的结构

python - 从字符串列表中获取子字符串与某个正则表达式匹配的子字符串列表

Node.js - 从 facebook graph api 获取我的帐户详细信息

ruby - 从标准输入获取下一个字节或 nil - Ruby

c - 如何从标准输入确定二维数组的高度和长度?