I have a python generator function which yields chunks of text. I would like to write a get
method for a tornado.web.RequestHandler
subclass that w
Here's a basic version of what you are describing. To avoid blocking you can pass your generator to the IOLoop via a callback function. The trick here is since you are not using a process that does actual IO and so has no os level process/file handler to add to the IOLoop via add_handler
, you can instead use a simple add_callback
call and call it repeatedly from within the callback function to keep the function in the IOLoop callback queue until the generator has finished.
import tornado.httpserver
import tornado.ioloop
import tornado.web
class TextHandler(tornado.web.RequestHandler):
@tornado.web.asynchronous
def get(self):
self.generator = self.generate_text(1000)
tornado.ioloop.IOLoop.instance().add_callback(self.loop)
def loop(self):
try:
text = self.generator.next()
self.write(text)
tornado.ioloop.IOLoop.instance().add_callback(self.loop)
except StopIteration:
self.finish()
def generate_text(self, n):
for x in xrange(n):
if not x % 15:
yield "FizzBuzz\n"
elif not x % 5:
yield "Buzz\n"
elif not x % 3:
yield "Fizz\n"
else:
yield "%s\n" % x
application = tornado.web.Application([
(r"/text/", TextHandler),
])
http_server = tornado.httpserver.HTTPServer(application)
http_server.listen(8888)
tornado.ioloop.IOLoop.instance().start()
It is also possible to use the new tornado's gen interface to async processes:
import tornado.httpserver
import tornado.ioloop
import tornado.web
import tornado.gen
class TextHandler(tornado.web.RequestHandler):
@tornado.web.asynchronous
@tornado.gen.engine
def get(self):
def cb(it, callback):
try:
value = it.next()
except StopIteration:
value = None
callback(value)
it = self.generate_text(1000)
while True:
response = yield tornado.gen.Task(cb, it)
if response:
self.write(response)
else:
break
self.finish()
def generate_text(self, n):
for x in xrange(n):
if not x % 15:
yield "FizzBuzz\n"
elif not x % 5:
yield "Buzz\n"
elif not x % 3:
yield "Fizz\n"
else:
yield "%s\n" % x
application = tornado.web.Application([
(r"/text/", TextHandler),
])
http_server = tornado.httpserver.HTTPServer(application)
http_server.listen(8888)
tornado.ioloop.IOLoop.instance().start()