gpt4 book ai didi

python - 如何编写一个可以获取函数或装饰函数的超时装饰器?

转载 作者:太空宇宙 更新时间:2023-11-03 12:02:11 25 4
gpt4 key购买 nike

我有以下超时创建装饰器函数:

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 , *args, **kwds)
else:
return self.func(self.HOST , *args, **kwds)
elif 'TOKEN' in function_args:
return self.func(self.TOKEN, *args, **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 , self.TOKEN , *args, **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 中,sleep 是通过...SIGALRM 实现的!

下面是发生的事情:

  • 外部装饰器要求在 10 秒内发出警报
  • 内部装饰器将附加参数传递给函数
  • 调用函数并调用sleep(20)
    • sleep 函数调用将警报超时重置为 20 秒!

这就是为什么函数实际持续 20 秒而不是 10 秒的原因...

关于python - 如何编写一个可以获取函数或装饰函数的超时装饰器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45425273/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com