Search code examples
pythonasynchronoustornado

Python with tornado - class implementation vs. too much async


Let's start with some example. There is library tornado-redis and below is example of using it.

import tornadoredis
import tornado.web
import tornado.gen

c = tornadoredis.Client()
c.connect()

class MainHandler(tornado.web.RequestHandler):
    @tornado.web.asynchronous
    @tornado.gen.engine
    def get(self):
        foo = yield tornado.gen.Task(c.get, 'foo')
        bar = yield tornado.gen.Task(c.get, 'bar')
        zar = yield tornado.gen.Task(c.get, 'zar')
        self.set_header('Content-Type', 'text/html')
        self.render("template.html", title="Simple demo", foo=foo, bar=bar, zar=zar)

And everything is simple. But I need to write a wrapper class. There is no problem with coding for me, but I think I am mistaken with async pattern.

My wrapper class should call redis class asynchronously, right!? Now do I have to implement my class also asynchronously in the way that the handler could call it with Task (async)? Then I would have two async places. What is the right way to keep Tronado async and keep it simple?

Handler --async call--> MyWrapper --async call--> tronado-redis

or

Handler --sync call--> MyWrapper --async call--> tronado-redis

or

Handler --async call--> MyWrapper --sync call--> tronado-redis

Solution

  • Asynchronous functions can only be called by other asynchronous functions. Since tornado-redis is asynchronous, the RequestHandler and everything in between must also be asynchronous.

    Note that the @tornado.web.asynchronous decorator is only used on RequestHandler methods - to make asynchronous methods outside of a RequestHandler you can use @gen.coroutine or @gen.engine by itself.