加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Python > 正文

如何编写一个超时装饰器,它可以获得一个函数或一个装饰函数?

发布时间:2020-12-20 13:19:03 所属栏目:Python 来源:网络整理
导读:我有以下超时创建装饰器功能: class TimeoutError(Exception): passdef timeout(seconds,error_message = 'Function call timed out'): def decorated(func): print "timeout: t" + func.__name__ def _handle_timeout(signum,frame): raise TimeoutError(
我有以下超时创建装饰器功能:

class TimeoutError(Exception): pass


def timeout(seconds,error_message = 'Function call timed out'):
    def decorated(func):
        print "timeout: t" + func.__name__
        def _handle_timeout(signum,frame):
            raise TimeoutError(error_message)


        def wrapper(*args,**kwargs):
            signal.signal(signal.SIGALRM,_handle_timeout)
            signal.alarm(seconds)
            try:
                print "timeout wrapper: t" + func.__name__
                result = func(*args,**kwargs)
            finally:
                signal.alarm(0)
            return result

        return functools.wraps(func)(wrapper)

    return decorated

另一个装饰者:

import inspect

class withHostAndToken(object):

    __name__ = "withHostAndToken"
    __doc__ = "Get the Host and Token for the API call"

    def __init__(self,func):
        print "withHostAndToken: t" + func.__name__
        self.func = func
        self.HOST = ''
        self.TOKEN = ''

    def __call__(self,*args,**kwds):

        if self.HOST == '':
            self.HOST = "HOST"
        if self.TOKEN == '':
            self.TOKEN = "TOKEN"

        argsspec = inspect.getargspec(self.func)
        function_args = argsspec[0]
        if 'HOST' in function_args:
            if 'TOKEN' in function_args:
                return self.func(self.HOST,self.TOKEN,**kwds)
            else:
                return self.func(self.HOST,**kwds)
        elif 'TOKEN' in function_args:
            return self.func(self.TOKEN,**kwds)

当我尝试将两者都应用于函数时,我不会得到要调用的函数代码:

@timeout(2)
@withHostAndToken
def testDecorators():
    print __name__
    while True:
        print '.'

testDecorators()

the output of this is:

withHostAndToken: testDecorators
timeout: withHostAndToken
timeout wrapper: withHostAndToken

Process finished with exit code 0

解决方法

你的问题不存在,装饰器的链接工作正常.

以下是与装饰器一起演示的示例代码:

>>> @timeout(2)
@withHostAndToken
def bar(*args):
    print(*args)
    i = 0;
    while True:
        dummy = sys.stderr.write('.')


>>> bar('foo')
host token foo
....................................................................................................................................................................................................................................................................................................................................................................................................................Traceback (most recent call last):
  File "<pyshell#48>",line 1,in <module>
    bar('foo')
  File "<pyshell#2>",line 10,in wrapper
    result = func(*args,**kwargs)
  File "<pyshell#5>",line 19,in __call__
    return self.func(self.HOST,**kwds)
  File "<pyshell#47>",line 7,in bar
    dummy = sys.stderr.write('.')
... message list truncate for brievety ...
  File "<pyshell#2>",line 4,in _handle_timeout
    raise TimeoutError(error_message)
TimeoutError: Function call timed out
>>>

因此,按预期大约2秒后,该功能正确中断.

但在您的用例中,您在最内部函数中使用了time.sleep.在Linux和其他Unix中,睡眠是通过… SIGALRM实现的!

所以这是发生的事情:

>外部装饰者要求在10秒钟内发出警报
>内部装饰器将附加参数传递给函数
>调用该函数并调用sleep(20)

>睡眠功能调用将闹钟超时重置为20秒!

这就是为什么这个功能实际上持续20秒而不是10秒…

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读