如何在Windows平台强制执行Python中的超时函数
我想做的就是,如果一个函数在规定时间内没有返回,就让它超时。
事情的起因是,urllib2支持对urlopen
设置超时,但在读取部分时却不支持,这导致我的程序卡住了。更改socket的defaulttimeout
没有效果。使用signal.sigalrm
也不行。我不想换成requests库,因为那样我得重写和测试很多代码。
我不想让一个线程去运行这个函数,然后再对线程设置超时,我想直接对这个函数设置超时。有没有什么好的办法?
2 个回答
0
是的,这个可以在Windows上实现,不需要信号,同时在其他操作系统上也能用。这里使用的是线程,但不是用来运行函数,而是用来设置超时的信号。具体的做法是创建一个新线程,等待一段时间,然后通过 _thread(在Python3中)或 thread(在Python2中)抛出一个异常。这个异常会在主线程中被抛出,如果发生了任何异常,with块就会退出。
import threading
import _thread # import thread in python2
class timeout():
def __init__(self, time):
self.time= time
self.exit=False
def __enter__(self):
threading.Thread(target=self.callme).start()
def callme(self):
time.sleep(self.time)
if self.exit==False:
_thread.interrupt_main() # use thread instead of _thread in python2
def __exit__(self, a, b, c):
self.exit=True
使用示例:
with timeout(2):
func()
在with块中的程序应该在2秒内完成,否则它将在2秒后被强制退出。
0
我喜欢在我的项目中使用David的这个类,在这里可以找到。我觉得它非常有效,而且它通过装饰器提供了一种简单的方法,可以在现有代码中实现。例如:
# Timeout after 30 seconds
@timeout(30)
def your_function():
...
注意:这个不是线程安全的!如果你在使用多线程,信号会被随机的线程捕获。不过对于单线程程序来说,这是最简单的解决方案。