twisted延迟/回调和异步执行

2024-05-15 23:33:24 发布

您现在位置:Python中文网/ 问答频道 /正文

我正试图找出如何使用twisted使代码更加异步。

  • 函数返回延迟对象
  • 然后我添加一个回调列表
  • 第一个回调将在deferred函数通过deferred_obj.callback提供某些结果后调用
  • 然后,在回调链中,第一个回调将处理数据并调用第二个回调
  • 等等

然而,链式回调不会被认为是异步的,因为它们是链式的,并且事件循环将继续并发地触发它们中的每一个,直到没有更多的,对吧?

但是,如果我有一个延迟对象,并且我将延迟obj.callback作为其回调附加在d.addCallback(deferred_obj.callback)中,那么这将被认为是异步的,因为延迟obj正在等待数据,然后传递数据的方法也在等待数据,但是,一旦i d.callback'd'对象处理数据,它就会调用deferred_obj.callback。但是,由于此对象被延迟,与链式回调不同,它将异步执行。。。对的?

假设我的所有代码都是非阻塞的,这意味着链式回调不是异步的,而链式延迟是异步的,对吗?


Tags: 数据对象方法函数代码obj列表callback
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()

如果您有长时间运行的同步代码,您可以使用一个合作者(twisted.internet.task)延迟线程或将其分解为短迭代

有点,但是在这种类型的事件处理中没有并发性。在代码返回到事件循环之前,不会调用新的回调。所以回调链是同步的。它在事件循环中只是异步的。

这是此类编程的一个警告,处理程序执行最快,并尽快返回事件循环。它不应该在处理程序中执行任何耗时的任务。

回调(默认情况下)是同步的。然而,正如Twisted doc所指出的:

If you need one Deferred to wait on another, all you need to do is return a Deferred from a method added to 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()

相关问题 更多 >