我试图在函数send
上设置超时。
我在这些帖子中找到了一些元素:
第一个似乎适用于每个函数而不是精确的函数,这就是我选择第二个函数的装饰器实现的原因。
我试图把它混合起来,我有这个:
from functools import wraps
import os
import signal
class TimeoutError(Exception):
pass
def timeout_func(error_message="Timeout in send pipe!"):
def decorator(func):
def _handle_timeout(signum, frame):
if args[0].action=="warn":
print "WARNING : ",error_message
elif args[0].action=="kill":
raise TimeoutError(error_message)
def wrapper(*args, **kwargs):
print args
signal.signal(signal.SIGALRM, _handle_timeout,args[0].action)
signal.alarm(args[0].seconds)
print str(args)
try:
result = func(*args, **kwargs)
finally:
signal.alarm(0)
return result
return wraps(func)(wrapper)
return decorator
class Link(object):
def __init__(self,timeout=1,action="warn"):
self.timeout=timeout
self.action=action
@timeout_func
def send(self,value):
print "working : ", value
它给了我这个:
在[6]中:l = Link()
在[7]中:l.send(1) -------------------------------------------------- ------------------------- TypeError Traceback(最近一次调用 最后)in() ----> 1 l.send(1)
TypeError:decorator()只取1个参数(给定2个)
我的问题是,我希望通过second
Link
将超时值self
传递给装饰器。我不完全理解这里的整个装饰机制,也无法弄清楚出了什么问题。
有人可以解释一下这个装饰器是如何工作的,我应该修改什么来修复它?或者,如果您想到一个更简单/更明确的解决方案来实现它?
答案 0 :(得分:0)
所以我一直在调试我的问题,我找到了一个有效的解决方案:
from functools import wraps
import signal
class TimeoutError(Exception):
pass
def timeout_func(f):
def _handle_timeout(signum, frame):
raise TimeoutError("timeout error")
def wrapper(*args):
signal.signal(signal.SIGALRM, _handle_timeout)
signal.setitimer(signal.ITIMER_REAL,args[0].timeout) #args[0] is self of Link class here
try:
result = f(*args,**kwargs)
finally:
signal.alarm(0)
return result
return wrapper
class Link(object):
def __init__(self,timeout=0.1,action="warn"):
self.timeout=timeout
self.action=action
def send(self,value): # I use this func to handle the exceptions
try:
self.send_timeout(value) # call the timeout function
except TimeoutError as e: # handle Timeout exception
if self.action=="warn":
print "WARNING : Timeout error in pipe send!"
elif self.action=="kill":
print "Killing Link : ", e
raise
except (Exception,KeyboardInterrupt) as e:
print "Exception in link : ", e
raise
@timeout_func # apply timeout decorator to this function
def send_timeout(self,value):
# DO STUFF HERE
要打电话:
l=Link()
l.send("any value")
我使用signal.setitimer(signal.ITIMER_REAL,args[0].timeout)
,因为它允许设置超时< 1秒,signal.signal()
不是这种情况,只接受整数作为计时器。