扭曲的递延/回调和异步执行
-
13-10-2019 - |
题
我正在尝试弄清楚如何使用扭曲使我的代码更加异步。
- 函数返回延期对象
- 然后我添加了回调列表
- 延期函数通过
deferred_obj.callback
- 然后,在回调链中,第一个回调将对数据进行一些操作,并调用第二个回调
- 等等。
但是,链式回调不会被视为异步,因为它们被链接了,事件循环将继续同时发射它们,直到不再有,对吗?
但是,如果我有一个递延对象,并且我将其作为回调为deferred_obj.callback,如在 d.addCallback(deferred_obj.callback)
然后,这将被视为异步,因为deferred_obj正在等待数据,然后将传递数据的方法也在等待数据,但是一旦i d.callback'd'对象处理数据,数据就会调用deferred_obj。但是,由于延迟了此对象,因此与链式回调的情况不同,它将异步执行...正确吗?
假设我的所有代码都是非阻止的,这意味着链式回调不是链接的,而链式延迟是对的,对吗?
解决方案
回调是(默认情况下)同步。但是,作为 扭曲的文档 指出:
如果您需要延期等待另一个,那么您所要做的就是从添加到AddCallbacks的方法中返回递延的方法。
因此,您可以使用它在回调链中进行一些异步处理。让我们这样做:
from twisted.internet import reactor, defer
def callback_func_2(result, previous_data):
# here we pass the result of the deferred down the callback chain
# (done synchronously)
print "calling function 1 on result:%s with previous result:%s" % (result, previous_data)
return result
def callback_func(result):
#let's do some asynchronous stuff in this callback
# simple trick here is to return a deferred from a callback
# instead of the result itself.
#
# so we can do asynchronous stuff here,
# like firing something 1 second later and have
# another method processing the result
print "calling function 1 on result:%s" % result
d = defer.Deferred()
reactor.callLater(1, d.callback, "second callback")
d.addCallback(callback_func_2, result)
return d
def do():
d = defer.Deferred()
reactor.callLater(1, d.callback, "first callback")
d.addCallback(callback_func)
return d
do()
reactor.run()
其他提示
有点,但是这种类型的事件处理没有并发。直到代码重新回到事件循环之前,不会打电话回来。因此,回调链是同步的。在事件循环中,它只是异步。
这是这种类型的编程的一个警告,处理程序最快地执行,并尽快返回事件循环。它不应在处理程序中完成任何耗时的任务。
使用延期不会使您的代码异步。
import time
from twisted.internet import defer
from twisted.internet import reactor
def blocking(duration, deferred):
print "start blocking"
time.sleep(duration)
print "finished blocking"
deferred.callback(True)
def other_task():
print "working..."
reactor.callLater(1, other_task)
def finish(result):
print "stopping reactor in 2sec"
reactor.callLater(2, reactor.stop)
def failed(reason):
print reason
print "stopping reactor in 2sec"
reactor.callLater(2, reactor.stop)
def main():
d = defer.Deferred()
d.addCallbacks(finish, failed)
reactor.callLater(0, blocking, 5, d)
if __name__ == "__main__":
reactor.callLater(0, other_task)
main()
reactor.run()
如果您有长期运行的同步代码,则可以使用合作者(twisted.internet.task)推迟或将其分解为简短的迭代。
不隶属于 StackOverflow