【发布时间】:2015-03-15 17:49:49
【问题描述】:
在 Twisted 中,似乎延迟对象只能在其回调触发后使用一次,这与我使用过的其他基于“承诺”的库相反:
from twisted.internet import defer
class Foo(object):
def __init__(self):
self.dfd = defer.Deferred()
def async(self):
return self.dfd
@defer.inlineCallbacks
def func(self):
print 'Started!'
result = yield self.async()
print 'Stopped with result: {0}'.format(result)
if __name__ == '__main__':
foo = Foo()
foo.func()
import time
time.sleep(3)
foo.dfd.callback('3 seconds passed!')
foo.func()
在标准输出中,有:
$ Started!
$ Stopped with result: 3 seconds passed!
$ Started!
$ Stopped with result: None
在我的情况下,我希望func 在reactor 线程中被一次又一次地调用。有什么方法可以确保yield 调用将始终返回延迟对象的“已解析”值而不引入额外的状态,如果是,那么最优雅的方法是什么?
更新
根据下面的建议,我实现了一个作为装饰器的解决方案:
import functools
def recycles_deferred(deferred_getter):
"""Given a callable deferred_getter that returns a deferred object, create
another function that returns a 'reusable' version of that deferred object."""
@functools.wraps(deferred_getter)
def _recycler(*args, **kwargs):
old_dfd = deferred_getter(*args, **kwargs)
new_dfd = defer.Deferred()
def _recycle(result):
new_dfd.callback(result)
return result
old_dfd.addCallback(_recycle)
return new_dfd
return _recycler
if __name__ == '__main__':
"""Demonstration of how this @recycles_deferred should be used."""
import time
from twisted.internet import defer
class O(object):
def __init__(self):
"""In practice this could representation a network request."""
self.dfd = defer.Deferred()
def do_something_with_result(self, result):
print 'Got result: {0}'.format(result)
return result
@recycles_deferred
def deferred_getter(self):
"""Return the deferred."""
return self.dfd
@defer.inlineCallbacks
def do_something_with_deferred(self):
result = yield self.deferred_getter()
print 'Got inline result: {0}'.format(result)
o = O()
o.dfd.addCallback(o.do_something_with_result) # Got result: foo
o.do_something_with_deferred() # Got inline result: foo
o.dfd.addCallback(o.do_something_with_result) # Got result: foo
# sleep 3 seconds, then resolve the deferred
time.sleep(3)
o.dfd.callback('foo')
o.do_something_with_deferred() # Got inline result: foo
o.dfd.addCallback(o.do_something_with_result) # Got result: foo
# the inline call to yield never returns None
o.do_something_with_deferred() # Got inline result: foo
o.do_something_with_deferred() # Got inline result: foo
o.do_something_with_deferred() # Got inline result: foo
【问题讨论】:
标签: python-2.7 twisted deferred