我编写了一个网络爬虫,我希望能够通过键盘停止它。我不希望程序在我中断它时死掉;它需要首先将数据刷新到磁盘。我也不想抓KeyboardInterruptedException
,因为持久数据可能处于不一致的状态。
我当前的解决方案是定义一个信号处理程序来捕获SIGINT
并设置一面旗帜;主循环的每次迭代都会在处理下一个 url 之前检查此标志。
但是,我发现如果系统恰好正在执行socket.recv()
当我发送中断时,我得到这个:
^C
Interrupted; stopping... // indicates my interrupt handler ran
Traceback (most recent call last):
File "crawler_test.py", line 154, in <module>
main()
...
File "/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/socket.py", line 397, in readline
data = recv(1)
socket.error: [Errno 4] Interrupted system call
并且进程完全退出。为什么会出现这种情况?有没有办法可以防止中断影响系统调用?
socket.recv()
调用底层 POSIX 兼容的recv
C 层中的函数,该函数又会返回错误代码EINTR
当进程收到一个SIGINT
在等待传入数据时recv()
。此错误代码可用于 C 端(如果您使用 C 进行编程)来检测recv()
返回不是因为套接字上有更多可用数据,而是因为进程收到了SIGINT
。无论如何,这个错误代码会被 Python 转换为异常,并且由于它永远不会被捕获,因此它会使用您看到的回溯来终止您的应用程序。解决办法很简单,就是抓住socket.error
,检查错误代码是否等于errno.EINTR
,默默地忽略异常。像这样的东西:
import errno
try:
# do something
result = conn.recv(bufsize)
except socket.error as (code, msg):
if code != errno.EINTR:
raise
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)