【发布时间】:2016-12-15 01:25:26
【问题描述】:
我正在尝试编写一个“更干净”的程序来释放一个潜在的写入器,该写入器在命名管道处被阻塞(因为没有读取器正在从管道读取)。然而,当没有作家被阻止写入管道时,清洁器本身不应该阻止。换句话说,“清理器”必须立即返回/终止,无论是否存在被阻止的写入器。
因此我搜索了“Python non-blocking read from named pipe”,得到了这些:
- How to read named FIFO non-blockingly?
- fifo - reading in a loop
- What conditions result in an opened, nonblocking named pipe (fifo) being "unavailable" for reads?
- Why does a read-only open of a named pipe block?
似乎他们建议简单地使用os.open(file_name, os.O_RDONLY | os.O_NONBLOCK) 应该没问题,这在我的机器上并没有真正起作用。我想我可能在某个地方搞砸了或误解了他们的一些建议/情况。但是,我自己真的想不通是怎么回事。
我找到了 Linux 手册页 (http://man7.org/linux/man-pages/man2/open.2.html),对 O_NONBLOCK 的解释似乎与他们的建议一致,但与我在我的机器上的观察不一致...
以防万一,我的操作系统是 Ubuntu 14.04 LTS 64 位。
这是我的代码:
import os
import errno
BUFFER_SIZE = 65536
ph = None
try:
ph = os.open("pipe.fifo", os.O_RDONLY | os.O_NONBLOCK)
os.read(ph, BUFFER_SIZE)
except OSError as err:
if err.errno == errno.EAGAIN or err.errno == errno.EWOULDBLOCK:
raise err
else:
raise err
finally:
if ph:
os.close(ph)
(不知道如何做 Python 语法高亮...)
本来只有第二个raise,但我发现os.open和os.read虽然没有阻塞,但也没有引发任何异常……我真的不知道作者会写入缓冲区!如果非阻塞read 没有引发异常,我应该如何知道何时停止阅读?
2016 年 8 月 8 日更新:
这似乎是满足我需要的解决方法/解决方案:
import os
import errno
BUFFER_SIZE = 65536
ph = None
try:
ph = os.open("pipe.fifo", os.O_RDONLY | os.O_NONBLOCK)
while True:
buffer = os.read(ph, BUFFER_SIZE)
if len(buffer) < BUFFER_SIZE:
break
except OSError as err:
if err.errno == errno.EAGAIN or err.errno == errno.EWOULDBLOCK:
pass # It is supposed to raise one of these exceptions
else:
raise err
finally:
if ph:
os.close(ph)
它将在read 上循环。每次读取内容时,它会将读取内容的大小与指定的BUFFER_SIZE 进行比较,直到达到 EOF(然后写入器将解除阻塞并继续/退出)。
我仍然想知道为什么read 中没有引发异常。
2016 年 8 月 10 日更新:
说清楚,我的总体目标是这样的。
我的主程序(Python)有一个线程作为阅读器。它通常在命名管道上阻塞,等待“命令”。有一个编写程序(Shell 脚本),它会在每次运行时将单行“命令”写入同一管道。
在某些情况下,编写器会在我的主程序启动之前或在我的主程序终止之后启动。在这种情况下,作者将阻塞等待读者的管道。这样,如果稍后我的主程序启动,它将立即从管道中读取以从被阻止的编写器那里获取“命令”——这不是我想要的。我希望我的程序忽略在它之前开始的作者。
因此,我的解决方案是,在读取器线程的初始化期间,我执行非阻塞读取以释放写入器,而不真正执行他们试图写入管道的“命令”。
【问题讨论】:
标签: python linux system-calls