我正在尝试实现一个函数,如果它在一定时间内无法完成(在线程挂起时出现问题)将会超时。这个answer似乎是最有希望的,有效地提供了一个API包装器,用来调用我的实际功能。它通常似乎有效(请参阅loop_forever),但在使用time.sleep
时无法停止。为什么超时不适用于睡眠定时器,这是否可以防止线程挂起?
import signal
import time
def timeout(func, args=(), kwargs={}, timeout_duration=1, default=None):
class TimeoutError(Exception):
pass
def handler(signum, frame):
raise TimeoutError()
# set the timeout handler
signal.signal(signal.SIGALRM, handler)
signal.alarm(timeout_duration)
try:
result = func(*args, **kwargs)
except TimeoutError as exc:
result = default
finally:
signal.alarm(0)
return result
def loop_forever():
x = 0
while True:
print x
try:
x += 1
except:
continue
def loop_forever_sleep():
x = 0
while True:
print x
try:
x += 1
time.sleep(10)
except:
continue
if __name__ == '__main__':
a = timeout(loop_forever) #Terminates
b = timeout(loop_forever_sleep) #Does not terminate
答案 0 :(得分:1)
问题是SIGALRM
系统调用时会引发time.sleep(10)
,这会导致您在该上下文中调用handler
。但是,您正在吞噬无限循环内发生的所有异常,因此TimeoutError
永远不会将其返回到timeout
函数,而是被except: continue
内部的loop_forever_sleep
代码忽略try
。只需从except
循环中移除while True
/ def loop_forever_sleep():
x = 0
while True:
print x
x += 1
time.sleep(10)
块,它就可以正常工作:
{{1}}