[Twisted-Python] Deferred.callback() v. Deferred.called

Jean-Paul Calderone exarkun at divmod.com
Wed Feb 8 13:53:35 EST 2006

On Wed, 8 Feb 2006 10:23:30 -0800 (PST), Lenny G Arbage <alengarbage at yahoo.com> wrote:
>I think I'm seeing a difference between when a
>deferred's callback is invoked and when the .called
>member variable is set, and was hoping someone might
>be able to explain.
>(And let me apologize in advance if what I'm trying to
>do is hairbrained or in some way abusive to the
>First, a little context.  I have some code that I use
>to test with, and it follows the standard deferred
>chaining pattern, i.e.,

Are you using trial?  If you use trial, testing Deferreds gets a lot easier.  If you're not using trial, you probably want to be using trial.

> [snip - some things that look like unit tests but don't use trial]
>...and I wanted to try putting all the trial
>invocations down in maintest, but still wait for the
>result of a preceeding test before invoking the next,
>so I made up a little function that does, basically,

Fortunately, waiting on things is what Deferreds do best.  Your maintest function (should you choose not to use trial, which there is basically no reason to do, so use trial) might look like this:

def maintest():
    tests = [test1, test2, test3]

    def runATest():
        if tests:
            d = tests.pop(0)()
            d.addCallback(lambda _: runATest())
            return d
    return runATest()

Now you can wait on the Deferred maintest returns.  Of course, you should really just use trial, since it handles all this for you, and with quite a few extra handy features as well.

>def waitForDeferredResult(d):
>    while not d.called:
>        reactor.iteratoe(0.1)
>    return d.result

This function is broken.  d.called isn't really public.  d.result isn't really public.  reactor.iterate() isn't really public.  You cannot poll a Deferred like this and expect it to work.  Lots of people have tried.  It just can't be done.

> [snip - description of why waitForDeferredResult doesn't work]

When you want to run some code after a Deferred has fired, put the code in a function, add the function as a callback.  That's the only supported way to do this.  It's the entire purpose of Deferreds.  It works wonderfully. :)


More information about the Twisted-Python mailing list