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

时间:2018-11-01 13:41:54

标签: 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缓冲区读取。但这是行不通的,我认为原因是子进程除非其stdin缓冲区接收到一个信号(如EOF),否则不会开始读取。作为证明,如果我在stdin.write之后关闭childProcess的stdin,则python代码将起作用并立即接收所有缓冲的包。这不是我想要的方式,因为我需要打开childProcess的stdin。那么,node.js是否有其他方法可以向childProcess发送信号以告知从stdin缓冲区读取数据?

(对不起,英语不好。

1 个答案:

答案 0 :(得分:0)

来自维基百科(强调我):

  

从终端输入永远不会“结束”(除非设备已断开连接),但是在终端中输入多个“文件”很有用,因此键序列被保留以指示输入结束。在UNIX中,键击转换为EOF是由终端驱动程序执行的,因此程序无需将终端与其他输入文件区分开。

无法向您发送期望的EOF字符。 EOF实际上不是一个存在的字符。在终端中时,可以按Windows上的键序列 ctrl z ctrl d 在类似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在特殊类型的“文件”中没有结尾。 必须定义该目标。终端已将该端定义为控制字符,但是在这里,您不是通过终端将数据传递到stdin,而是必须自己进行管理。

只需关闭文件

  

输入[...]从未真正“结束”(除非设备已断开连接)

在这里关闭stdin可能是最简单的解决方案。 stdin是一个无限文件,因此一旦完成对其的写入,只需将其关闭。

期待自己的控制字符

另一个选择是定义您自己的控制字符。您可以在这里使用任何您想要的东西。下面的示例使用NULL字节。

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

蟒蛇
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");