22

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

>>> fifo_write = open('fifo', 'w')

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

>>> fifo_read = open('fifo', 'r')
>>> fifo.read()

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

>>> fifo_write.write("some testing data\n")
>>> fifo_write.flush()

预期的行为是在第二个解释器上调用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

而先进先出阅读器仍在等待。但是,如果我打电话,fifo_writer.close()那么数据就会被刷新。如果我使用 shell 命令来馈送管道:

$ echo "some data" > fifo

那么阅读器的输出是:

>>> fifo_read.read()
'some data\n'

有没有人经历过这个?如果是这样,是否有解决方法?我当前的操作系统是带有 Linux 2.6.38 的 Ubuntu 11.04。

4

2 回答 2

13

read()在到达 EOF 之前不会返回。

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

于 2011-08-13T02:34:44.910 回答
7

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

fifo_read = open('fifo', 'r', 0)

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

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

于 2013-09-06T11:46:20.620 回答