[Twisted-Python] Question about RequestHandlers and inlinecallbacks
![](https://secure.gravatar.com/avatar/917e9407f1027d3e6e4bc1a16d49b632.jpg?s=120&d=mm&r=g)
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). The problem is that in process(self), a deferred is created but process() ends finishes without outputting anything to the web browser. Eventually, the associated callback is triggered but the request has already been serviced. What I really want is process() to wait until the client.getPage() is finished. 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? I have included some sample code. Cheers, Andrew ____________________________________________________________________________________ Looking for last minute shopping deals? Find them fast with Yahoo! Search. http://tools.search.yahoo.com/newsearch/category.php?category=shopping """ inlineExample.py A simple example to see if I can use inlinecallbacks from an RequestHandler """ from twisted.web import http, client from twisted.internet import defer def gotPage(result): print result return defer.returnValue(result) class MyRequestHandler(http.Request): @defer.inlineCallbacks def __process__(self): aResult = yield client.getPage("http://localhost").addCallback(gotPage) self.setHeader('Content-Type', 'text/html') self.write(aResult) self.finish() def process(self): """ I want process to wait until client.getPage is finished. """ self.__process__() class MyHttp(http.HTTPChannel): requestFactory = MyRequestHandler class MyHttpFactory(http.HTTPFactory): protocol = MyHttp if __name__ == "__main__": from twisted.internet import reactor reactor.listenTCP(8000, MyHttpFactory()) print "server running" reactor.run()
![](https://secure.gravatar.com/avatar/7ed9784cbb1ba1ef75454034b3a8e6a1.jpg?s=120&d=mm&r=g)
On Thu, 24 Jan 2008 13:03:17 -0800 (PST), Andrew Francis <andrewfr_ice@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
participants (2)
-
Andrew Francis
-
Jean-Paul Calderone