pythontornado

Mix tornado.gen.coroutine with async/await?


I need to change the following legacy tornado code to call an async function async def my_async1(self).

class MyHandler(tornado.web.RequestHandler):
    @gen.coroutine
    def get(self, action):
        ....
        

Can they be mixed? How to refactory the code?

class MyHandler(tornado.web.RequestHandler):
    @gen.coroutine 
    async def get(self, action):
        ....
        await self.my_async() # ? 
     

Can I just remove @gen.coroutine and add async? Are they exactly the same?


Solution

  • Yeah, they are almost the same. @gen.coroutine is from old days when Python didn't have async/await keywords. So @gen.coroutine was used for turning regular functions (or generators) into asynchronous generators.

    For newer python versions (3.5+), the async/await syntax should be preferred over @gen.coroutine.

    Keep these things in mind while converting the functions:

    1. Don't decorate async def functions with @gen.coroutine (like you've done in your second code example).
    2. Replace yield keyword with await keyword.
    3. yield None statement works but await None doesn't.
    4. You can yield a list (such as yield [f1(), f2()]), but with await, use await gen.multi([f1(), f2()]) or await asyncio.gather(f1(), f2()). (Thanks to Ben for mentioning this.)