如何在Python中正确写入FIFO?

Thi*_*uda 17 python linux fifo mkfifo

当我在Python中打开用于写入的FIFO(命名管道)时,会发生一些非常奇怪的事情.考虑当我尝试打开FIFO以便在交互式解释器中写入时会发生什么:

>>> fifo_write = open('fifo', 'w')
Run Code Online (Sandbox Code Playgroud)

上面的行阻塞,直到我打开另一个解释器并键入以下内容:

>>> fifo_read = open('fifo', 'r')
>>> fifo.read()
Run Code Online (Sandbox Code Playgroud)

我不明白为什么我不得不等待管道打开阅读,但我们跳过它.上述代码将阻塞,直到有预期的数据可用.但是,假设我回到第一个解释器窗口并键入:

>>> fifo_write.write("some testing data\n")
>>> fifo_write.flush()
Run Code Online (Sandbox Code Playgroud)

预期的行为是,在第二个解释器上,调用read将返回,我们将在屏幕上看到数据,除非发生在我身上.如果我打电话os.fsync给以下情况发生:

>>> import os
>>> fifo_write.flush()
>>> os.fsync(fifo_write.fileno())
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
OSError: [Errno 22] Invalid argument
Run Code Online (Sandbox Code Playgroud)

而fifo读者仍在等待.但是,如果我打电话,fifo_writer.close()那么数据会被刷新.如果我使用shell命令来提供管道:

$ echo "some data" > fifo
Run Code Online (Sandbox Code Playgroud)

然后读者输出是:

>>> fifo_read.read()
'some data\n'
Run Code Online (Sandbox Code Playgroud)

有没有人经历过这个?如果是这样,有一个解决方法吗?我目前的操作系统是Ubuntu 11.04和Linux 2.6.38.

Mar*_*tos 10

read() 直到达到EOF才会返回.

您可以尝试指定要读取的字节数,例如read(4).这仍将阻塞,直到写入足够的字节为止,因此生产者必须至少写入那么多字节然后调用flush().

  • @ThiadodeArruda到底是什么说法? (2认同)

Mik*_*ike 6

为避免刷新的需要,请在不缓冲的情况下打开文件:

fifo_read = open('fifo', 'r', 0)
Run Code Online (Sandbox Code Playgroud)

这将删除高级缓冲。数据直接进入操作系统,作为一个先进先出,它们从未真正写入磁盘,而是通过先进先出缓冲区直接传递给读取器,因此您不需要同步。

当然,正如您在评论中指出的那样,您应该首先使用shellos.mkfifo()mkfifo在 shell 上创建 fifo 。