Python 在具有修饰符的类中对函数超时

Python 在具有修饰符的类中对函数超时,python,python-2.7,timeout,decorator,Python,Python 2.7,Timeout,Decorator,我正在尝试对函数send设置超时 我在这些帖子中发现了一些元素: 第一个似乎适用于每个函数,而不是一个精确的函数,这就是为什么我选择像第二个一样的装饰器实现 我试着把它混在一起,我发现: from functools import wraps import os import signal class TimeoutError(Exception): pass def timeout_func(error_message="Timeout in send pipe!"):

我正在尝试对函数
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()

In[7]:l.send(1) ---------------------------------------------------------------------------TypeError回溯(最近的调用 最后)在() ---->1.发送(1)

TypeError:decorator()正好接受1个参数(给定2个)

我的问题是,我想通过
链接
self
将超时值
second
传递给装饰程序。我不完全理解这里的整个装饰机制,也不知道哪里出了问题


有人能解释一下这个装饰器是如何工作的吗?我应该修改什么来修复它?或者如果您想到一个更简单/更明确的解决方案来实现它?

因此我一直在调试我的问题,并找到了一个可行的解决方案:

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\u REAL,args[0].timeout)
,因为它允许设置<1秒的超时,而
signal.signal()的情况则不同,它只接受整数作为计时器