[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()
returns.
>
>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
suspect.
What you want process() to look like is this:
def process(self):
pageDeferred = client.getPage(...)
def gotPage(result):
self.write(result)
self.finish()
def gotError(err):
log.err(err, "process getPage call failed")
self.finish()
pageDeferred.addCallbacks(gotPage, gotError)
If you used inlineCallbacks, then it would look like this:
def process(self):
try:
result = yield client.getPage(...)
except Exception, err:
log.err(err, "process getPage call failed")
else:
self.write(result)
self.finish()
process = inlineCallbacks(process)
Jean-Paul
More information about the Twisted-Python
mailing list