[Twisted-Python] Question about RequestHandlers and inlinecallbacks

Jean-Paul Calderone exarkun at divmod.com
Thu Jan 24 17:31:11 EST 2008

On Thu, 24 Jan 2008 13:03:17 -0800 (PST), Andrew Francis <andrewfr_ice at yahoo.com> wrote:
>Hello Folks:
>I am starting to learn inlinecallbacks. I am trying to
>do the following:
>from within a RequestHandler, I get a web page with
>the client.getPage() method. I subsequently return the
>web page to the requesting web browser.
>The problem -
>The web browser hangs. However the
>requestHandler.writes are echoed to standard output
>(or error).

Well... almost.  Your attached example doesn't actually print out
what is passed to Request.write().  It prints out what is passed to
the callback of the Deferred returned by getPage.

>The problem is that in process(self), a deferred is
>created but process() ends finishes without outputting
>anything to the web browser.

As it must.  The output is the result of a network operation.  It is
exceedingly unlikely that it will be able to happen before process()

>Eventually, the associated callback is triggered but
>the request has already been serviced.

I'm not sure what this means.  What is "the associated callback"?

>What I really want is process() to wait until the
>client.getPage() is finished.

That's what Deferreds are for.  Whatever you want to happen after
client.getPage() has happened, you should put into a callback and
attach that callback to the Deferred you get (like you did with
gotPage, almost).

>What I am unclear about is how to properly structure
>the programme to get the appropriate behaviour. I am
>assuming this is possible. If so, what am I missing?

The part where you got confused is the part that uses inlineCallbacks,
I think.

You defined a gotPage callback which uses defer.returnValue.  This is
totally bogus.  If you want a callback to return a value, then you just
return it.  defer.returnValue lets you specify the result of a Deferred
returned by a call to a function decorated with inlineCallbacks.

Your gotPage function has not been so decorated, so there's your bug I

What you want process() to look like is this:

    def process(self):
        pageDeferred = client.getPage(...)
        def gotPage(result):
        def gotError(err):
            log.err(err, "process getPage call failed")
        pageDeferred.addCallbacks(gotPage, gotError)

If you used inlineCallbacks, then it would look like this:

    def process(self):
            result = yield client.getPage(...)
        except Exception, err:
            log.err(err, "process getPage call failed")
    process = inlineCallbacks(process)


More information about the Twisted-Python mailing list