twisted deferred/callbacks and asynchronous execution

10,979

Solution 1

The callbacks are (by default) synchronous. However, as the Twisted doc points out:

If you need one Deferred to wait on another, all you need to do is return a Deferred from a method added to addCallbacks.

So you can use that to do some asynchronous processing in your callback chain. Let's do that:

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()

Solution 2

Sort of, but there is no concurrency in this type of event processing. No new callback will be called until the code gets back to the event loop. So the chain of callbacks is synchronous. It's only asynchronous in the event loop.

This is one caveat of this type of programming, the handlers most execute quickly, and get back to the event loop ASAP. It should not do any time consuming task in a handler.

Share:
10,979

Related videos on Youtube

mayotic
Author by

mayotic

Updated on June 04, 2022

Comments

  • mayotic
    mayotic almost 2 years

    I'm trying to figure out how can i make my code more asynchronous using twisted.

    • A function returns a deferred object
    • then i add a list of callbacks
    • the first callback will be called after the deferred function provides some result through deferred_obj.callback
    • then, in the chain of callbacks, the first callback will do something with the data and call the second callback
    • and etc.

    however chained callbacks will not be considered asynchronous because they're chained and the event loop will keep firing each one of them concurrently until there is no more, right?

    However, if I have a deferred object, and I attach as its callback the deferred_obj.callback as in d.addCallback(deferred_obj.callback) then this will be considered asynchronous, because the deferred_obj is waiting for the data, and then the method that will pass the data is waiting on data as well, however once i d.callback 'd' object processes the data then it call deferred_obj.callback however since this object is deferred, unlike the case of chained callbacks, it will execute asynchronously... correct?

    Assuming all of my code is non-blocking, this means that chained callbacks are NOT asynchronous while chained deferreds are, correct?

    • Jochen Ritzel
      Jochen Ritzel over 13 years
      Please take this and make use of it in your wall of text: ...........
    • Tommy
      Tommy over 13 years
      he meant your question is very hard to read as it's a wall of text, so you should use some more space...
    • Kos
      Kos almost 12 years
      He meant interpunction in general.
  • mayotic
    mayotic over 13 years
    so if deferred object has a chain of callbacks, the code will not get back to the event loop until the whole chain has been passed; however, if i break up this chain using deferred objects, i allow the code to go back to the event loop and check for other events; correct?
  • Keith
    Keith over 13 years
    Yes, exactly. That's the general pattern. You might have to introduce timers into the event loop to process large chunks of data.
  • mayotic
    mayotic over 13 years
    yes thank you for the example, i am using a similar model like the one u portrayed in my program