tl;博士
在 Python 中读取管道时,我是否应该处理 EINTR“系统调用中断”错误,如果是,我该如何测试这样的代码?
描述
在下面的回溯中,self._dataq
是一个multiprocessing.Queue
(从技术上讲,我正在使用该billiard
库,但我认为它们基本上是相同的代码)。Python 子进程偶尔会写入队列的另一端。我认为发生的事情是一个系统调用正在读取为队列提供数据的管道,并且一个信号到达——可能是来自第二个 Ctrl+C 事件的 SIGINT(第一个 SIGINT 发生在您^C
在第二行看到用户的位置记录输出,并且我的信号处理程序捕获了该 SIGINT,正如您在日志中的 WARNING 消息中看到的那样)。
[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._dataq
何时self.timedout()
开始返回True
。
import queue
while True:
try:
result = self._dataq.get(timeout=0.1)
except queue.Empty:
if self.timedout():
self.close()
raise MyTimedoutError()
else:
break
问题
如果我关于为什么IOError
发生的理论是正确的,那么当它们是由中断的系统调用引起的时,上面的try
...except
块应该捕获并忽略s 。IOError
如果它是导致 EINTR 错误的信号,那么仅仅回到 Python 中运行该except IOError:
语句的行为将允许 Python 级别的信号处理程序运行。
那是对的吗?如果是这样,是否可以在我的代码中测试此更改?对我来说,如何编写不包含严重竞争条件的单元测试并不明显。