Python:在管道读取循环中需要捕获EINTR吗?

2024-07-07 09:20:50 发布

您现在位置:Python中文网/ 问答频道 /正文

Tl;DR<EH3>

在读取Python中的管道时,我是否应该处理EINTR“系统调用中断”错误,如果是,如何测试这些代码?在

说明

在下面的回溯中,self._dataqmultiprocessing.Queue(技术上,我使用的是billiard库,但我认为它们基本上是相同的代码)。Python子进程偶尔会写入队列的另一端。我想发生的是,一个系统调用正在读取为队列提供数据的管道,然后一个信号到达了——可能是来自第二个Ctrl+C事件的SIGINT(第一个SIGINT发生在日志输出的第二行,用户的^C,我的信号处理程序捕捉到了这个SIGINT,您可以在日志中的警告消息中看到)。在

[INFO     2014-03-05 14:16:06,000] Doing some work, la-dee-da
^C[WARNING 2014-03-05 14:16:07,344] Commencing shutdown. (Signal SIGINT, process 2469.). Press Ctrl+C again to exit immediately.
[DEBUG    2014-03-05 14:16:07,347] Terminating subprocess
Traceback (most recent call last):
[... a bunch of stuff omitted]
  File "mycode.py", line 97, in __next__
    result = self._dataq.get(timeout=0.1)
  File "/usr/local/lib/python2.7/site-packages/billiard/queues.py", line 103, in get
    if timeout < 0 or not self._poll(timeout):
IOError: [Errno 4] Interrupted system call

上面回溯中的语句result = self._dataq.get(timeout=0.1)位于如下所示的循环中间。循环的主要目的是,当self.timedout()开始返回True时,我可以放弃从self._dataq读取数据。在

^{pr2}$

问题

如果我关于^{发生的原因的理论是正确的,那么上面的tryexcept块应该捕捉并忽略IOError是由中断的系统调用引起的。如果是一个信号导致了EINTR错误,那么仅仅返回Python运行except IOError:语句就可以运行Python级别的信号处理程序。在

对吗?如果是这样,有没有可能在我的代码中测试这个更改?对于我来说,如何编写一个不包含严重竞争条件的单元测试并不明显。在


Tags: 代码selfget管道信号队列系统错误
2条回答

我将称之为Python中的bug。我找不到允许^{}EINTR上引发IOError的任何文档(尽管在其他I/O问题上引发是有意义的,这就是为什么您应该在忽略引发的异常之前检查errno属性;请参见^{}),而且它不会直接映射到任何提供这种行为的低级C函数。在C级别上有处理所有EINTRsome discussion,但这并没有使它成为3.4(我怀疑它是否会成为2.x版本),所以这可能仍然是一个值得报道的游戏。在

python3.5通过将处理EINTR的责任放在Python运行时而不是应用程序代码上来解决这个问题。请参见PEP 475和{a2}。在

相关问题 更多 >