当我在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'
有没有人经历过这个?如果是这样,有一个解决方法吗?我目前的操作系统是Ubuntu 11.04和Linux 2.6.38。
答案 0 :(得分:10)
read()
在到达EOF之前不会返回。
您可以尝试指定要读取的字节数,例如read(4)
。这仍将阻塞,直到写入足够的字节为止,因此生产者必须至少写入那么多字节,然后调用flush()
。
答案 1 :(得分:2)
为避免需要刷新,请在不缓冲的情况下打开文件:
fifo_read = open('fifo', 'r', 0)
这将删除高级缓冲。数据直接转到操作系统,作为一个fifo,它们永远不会实际写入磁盘,而是通过fifo缓冲区直接传递给读取器,因此您不需要同步。
当然,您应该首先在shell中使用os.mkfifo()
或mkfifo
创建fifo,正如您在评论中所指出的那样。