用 Python 编写 TTL 装饰器
我正在尝试用 python 编写一个 TTL 装饰器。 基本上,如果函数不这样做,我会给它引发异常 在选定的时间内回答。
您可以在 http://sebulba.wikispaces.com/recipe+thread2 上找到 thead2 片段
from thread2 import Thread
""" A TTL decorator. """
class Worker(Thread):
def __init__(self, q, f, args, kvargs):
Thread.__init__(self)
self.q = q
self.f = f
self.args = args
self.kvargs = kvargs
def run(self,):
try:
res = (True, self.f(*self.args, **self.kvargs))
self.q.put(res)
except Exception, e:
self.q.put((False, e))
class Referee(Thread):
def __init__(self,q, ttl,exception_factory):
Thread.__init__(self)
self.exception_factory=exception_factory
self.q=q
self.ttl=ttl
def run(self):
time.sleep(self.ttl)
res = (False, self.exception_factory())
self.q.put(res)
def raise_if_too_long(ttl, exception_factory=lambda :RuntimeError("Timeout")):
def raise_if_too_long_aux(f):
def ritl(*args,**kvargs):
q = Queue.Queue(2)
referee = Referee(q, ttl, exception_factory)
worker = Worker(q,f,args,kvargs)
worker.start()
referee.start()
(valid, res)= q.get(1)
q.task_done()
referee.terminate()
worker.terminate()
if valid:
return res
else:
raise res
return ritl
return raise_if_too_long_aux
但是,我得到了一些非常糟糕的结果。 似乎有时该函数还可以正常返回 装饰器在达到 TTL 并出现错误之前不会返回 提高。
你看到这段代码有什么问题吗? 在 python 中是否有一种通用的方法/库来编写带有 TTL 的函数?
I'm trying to write a TTL decorator in python.
Basically I give it raise an exception if the function doesn't
answer in the selected time.
You can find the thead2 snippets on http://sebulba.wikispaces.com/recipe+thread2
from thread2 import Thread
""" A TTL decorator. """
class Worker(Thread):
def __init__(self, q, f, args, kvargs):
Thread.__init__(self)
self.q = q
self.f = f
self.args = args
self.kvargs = kvargs
def run(self,):
try:
res = (True, self.f(*self.args, **self.kvargs))
self.q.put(res)
except Exception, e:
self.q.put((False, e))
class Referee(Thread):
def __init__(self,q, ttl,exception_factory):
Thread.__init__(self)
self.exception_factory=exception_factory
self.q=q
self.ttl=ttl
def run(self):
time.sleep(self.ttl)
res = (False, self.exception_factory())
self.q.put(res)
def raise_if_too_long(ttl, exception_factory=lambda :RuntimeError("Timeout")):
def raise_if_too_long_aux(f):
def ritl(*args,**kvargs):
q = Queue.Queue(2)
referee = Referee(q, ttl, exception_factory)
worker = Worker(q,f,args,kvargs)
worker.start()
referee.start()
(valid, res)= q.get(1)
q.task_done()
referee.terminate()
worker.terminate()
if valid:
return res
else:
raise res
return ritl
return raise_if_too_long_aux
However, I get some pretty bad result.
It seems like sometimes the function is returning alright yet
the decorator doesn't return until the TTL is reached and the error
raises.
Do you see something wrong in this code?
Is there a common way/library to write function with a TTL in python?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
提供的代码有点难以理解——如何在正确的时间、正确的线程中的正确位置引发异常?
考虑这个粗略流程:
使用目标函数调用装饰器函数。 返回一个函数,其中:
(您需要设计一种方法来捕获线程的输出...)
请参阅 http: //docs.python.org/library/threading.html 有关线程超时的信息...
(或者只是开始使用 erlang
:)
The code provided is a bit tough to follow -- how is it going to raise an exception in the right place at the right time in the right thread?
Consider this rough flow:
Decorator function called with target function. Return a function which:
(You would need to devise a way to capture the output of the thread...)
See http://docs.python.org/library/threading.html for info on the threading timeout...
(Or just start using erlang
:)
如果您希望在超过超时后终止函数的执行,您可能需要尝试具有该功能的代码。 要使用该模块,所需要做的就是将您的函数作为
add_timeout
的参数调用,并且返回值可以运行。 调用后,可以轮询对象的ready
属性,并且可以通过value
属性访问返回的任何内容。 代码的文档应该为可用 API 的其余部分提供解释。[代码长度已编辑]请参阅timeout.py了解源代码。
附录:
还有另一种看待问题的方式。 您可以将函数及其参数提交给执行引擎,该执行引擎可以对函数可以运行的时间强制执行超时,而不是装饰函数以使其具有生存时间。 我上面最初的答案是大约八年前解决这个问题的。 在进一步研究该主题后,我可以推荐以下模块吗? 它后面的模块用于测试和演示
异步
模块的使用。asynchronous.py
test_asynchronous.py
If you want the function's execution to be terminated after the timeout has been exceeded, you might want to try code that has that capability. To use the module, all that needs to be done is for your function to be called as an argument to
add_timeout
, and the returned value can run. Once called, the object'sready
property can be polled, and anything returned can be accessed via thevalue
property. The code's documentation should provide an explanation for the rest of the available API.[code redacted for length] See timeout.py for source.
Addendum:
There is another way of looking at the problem. Instead of decorating a function to have a time-to-live, you could submit the function and its arguments to an execution engine that can enforce a timeout on how long it can run for. My original answer up above was a solution to this problem about eight years ago. After further study on the subject, may I recommend the following module instead? The module that follows it is used for testing and demonstrating usage of the
asynchronous
module.asynchronous.py
test_asynchronous.py