扭曲的延迟/回调和异步执行
Posted
技术标签:
【中文标题】扭曲的延迟/回调和异步执行【英文标题】:twisted deferred/callbacks and asynchronous execution 【发布时间】:2011-05-31 07:44:18 【问题描述】:我正在尝试弄清楚如何使用twisted 使我的代码更加异步。
函数返回延迟对象 然后我添加一个回调列表 第一个回调将在延迟函数通过deferred_obj.callback
提供一些结果后调用
然后,在回调链中,第一个回调将对数据进行处理并调用第二个回调
等等
但是,链式回调不会被视为异步,因为它们是链式的,并且事件循环将继续同时触发它们中的每一个,直到不再有,对吧?
但是,如果我有一个延迟对象,并且我将 deferred_obj.callback 作为其回调附加在d.addCallback(deferred_obj.callback)
中,那么这将被认为是异步的,因为 deferred_obj 正在等待数据,然后将通过的方法数据也在等待数据,但是一旦 d.callback 'd' 对象处理数据然后它调用 deferred_obj.callback 但是由于这个对象是延迟的,与链式回调的情况不同,它将异步执行......正确?
假设我的所有代码都是非阻塞的,这意味着链式回调不是异步的,而链式延迟是异步的,对吗?
【问题讨论】:
请把它用在你的文字墙里:...........
他的意思是你的问题很难阅读,因为它是一堵文字墙,所以你应该使用更多的空间......
他的意思是一般的interpunction。
【参考方案1】:
回调(默认情况下)是同步的。但是,正如Twisted doc 指出的那样:
如果您需要一个 Deferred 来等待另一个,您需要做的就是从添加到 addCallbacks 的方法中返回一个 Deferred。
因此,您可以使用它在回调链中进行一些异步处理。让我们这样做:
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()
【讨论】:
是的,谢谢你的例子,我正在使用与你在我的程序中描绘的相似的模型【参考方案2】:有点,但在这种类型的事件处理中没有并发。在代码返回事件循环之前,不会调用新的回调。所以回调链是同步的。它只是在事件循环中是异步的。
这是此类编程的一个警告,处理程序执行速度最快,并尽快返回事件循环。它不应该在处理程序中执行任何耗时的任务。
【讨论】:
所以如果延迟对象有一个回调链,代码将不会回到事件循环,直到整个链都通过了;但是,如果我使用延迟对象打破这个链,我允许代码返回事件循环并检查其他事件;对吗? 是的,完全正确。这是一般模式。您可能必须在事件循环中引入计时器来处理大量数据。【参考方案3】:使用延迟不会使您的代码异步。
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()
如果您有长时间运行的同步代码,您可以 deferToThread 或使用协作器 (twisted.internet.task) 将其分解为短迭代
【讨论】:
【参考方案4】:如果您想使用简洁的方法使您的代码更加异步,请查看此框架:
https://github.com/iogf/untwisted
它有简洁的代码和清晰的文档。处理异步模型的方法很简单。
【讨论】:
以上是关于扭曲的延迟/回调和异步执行的主要内容,如果未能解决你的问题,请参考以下文章