[Twisted-Python] Please help with Deferreds

Andrew Bennetts andrew-twisted at puzzling.org
Sun Aug 25 21:43:46 EDT 2002


On Sat, Aug 24, 2002 at 10:05:30PM +0300, Tommi Virtanen wrote:
> 	Can anyone explain the behaviour of the
> 	following?
> 
> #!/usr/bin/python
> import sys
> from twisted.internet import defer, reactor
> d=defer.Deferred()
> d.callback(0)
> d2=defer.Deferred()
> d.addCallback(lambda x,d2=d2: d2)

So you've effectively done:

d = defer.Deferred()
d2 = defer.Deferred()
d.callback(d2)

> # switch the comment sign on the next two and it'll
> # print not 1 but a Deferred. Why?
> #reactor.callLater(0, lambda d2=d2: d2.callback(1))

Which is effectively:
# reactor.callLater(0, d2.callback, 1)

> d2.callback(1)
> 
> d.addCallback(lambda x:sys.stdout.write(repr(x)+'\n'))
> d.addBoth(lambda x:reactor.stop())

Note that these callbacks will fire immediately upon adding them.

> reactor.run()

And of course, you don't need to do reactor.run() unless you're using
the reactor.callLater version of this code.

So, this is easy...

Consider what happens to your first Deferred, d, with that line
uncommented:
  d = defer.Deferred()      # 1. Create it
  d.callback(d2)            # 2. call it with some value (d2)
  reactor.callLater(....)   # 3. this doesn't happen yet
  d.addCallback(....)       # 4. this fires *immediately*, and writes
                                 the value from 2., which is d2

So that's why it prints the Deferred in that case.  Now back the way the
code is originally:
  d = defer.Deferred()      # 1. Create it
  d.callback(d2)            # 2. call it with some value (d2)
  d2.callback(1)            # 3. call d2 with another value (1)
  d.addCallback(....)       # 4. this fires *immediately*, and writes 
                                 the value from 2. -- which is 1???

That does confuse me.  Somehow, if a callback has a result which is
another Deferred, it does something special to automatically call that
Deferred, which I didn't realise and seems nasty to me.  I thought that
was only meant to happen if you explicitly called chainDeferred?

I've just re-read doc/howto/defer and I see that this is in fact
explained under the heading "Chain Deferreds", but I'm still curious as
to why this behaviour is necessary... "explicit is better than
implicit", etc :)

Anyway, I hope you now understand why that code behaves the way it
does...

-Andrew.





More information about the Twisted-Python mailing list