我有这个装饰器直接取自我在网上找到的一个例子:
class TimedOutExc(Exception):
pass
def timeout(timeout):
def decorate(f):
def handler(signum, frame):
raise TimedOutExc()
def new_f(*args, **kwargs):
old = signal.signal(signal.SIGALRM, handler)
signal.alarm(timeout)
try:
result = f(*args, **kwargs)
except TimedOutExc:
return None
finally:
signal.signal(signal.SIGALRM, old)
signal.alarm(0)
return result
new_f.func_name = f.func_name
return new_f
return decorate
如果 f 函数超时,它会抛出异常。
嗯,它可以工作,但是当我在多处理函数上使用这个装饰器并由于超时而停止时,它不会终止计算中涉及的进程。我怎样才能做到这一点?
我不想启动异常并停止程序。基本上我想要的是当 f 超时时,让它返回 None 然后终止所涉及的进程。
虽然我同意亚伦回答的要点,但我想详细说明一下。
启动的进程multiprocessing
必须停止在要装饰的函数中;我认为这不能从装饰器本身一般且简单地完成(装饰函数是唯一知道它启动了什么计算的实体)。
而不是让装饰函数 catchSIGALARM
,你也可以抓住你的习惯TimedOutExc
例外——这可能更灵活。那么你的例子将变成:
import signal
import functools
class TimedOutExc(Exception):
"""
Raised when a timeout happens
"""
def timeout(timeout):
"""
Return a decorator that raises a TimedOutExc exception
after timeout seconds, if the decorated function did not return.
"""
def decorate(f):
def handler(signum, frame):
raise TimedOutExc()
@functools.wraps(f) # Preserves the documentation, name, etc.
def new_f(*args, **kwargs):
old_handler = signal.signal(signal.SIGALRM, handler)
signal.alarm(timeout)
result = f(*args, **kwargs) # f() always returns, in this scheme
signal.signal(signal.SIGALRM, old_handler) # Old signal handler is restored
signal.alarm(0) # Alarm removed
return result
return new_f
return decorate
@timeout(10)
def function_that_takes_a_long_time():
try:
# ... long, parallel calculation ...
except TimedOutExc:
# ... Code that shuts down the processes ...
# ...
return None # Or exception raised, which means that the calculation is not complete
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)