Search code examples
python-3.xasync-awaitpython-asynciotornadocyclone

Alternate of @cyclone.web.asynchronous in tornado enviroment


We are shifting our code infra from cyclone to tornado now. Previously we were using @cyclone.web.asynchronous for one of our api for non blocking async call in cyclone(so that we do not block the UI). What is the alternative of this in tornado, @tornado.web.asynchronous is not working in tornado 6.1. My code for cyclone is someting like this

class ABCHandler(cyclone.web.RequestHandler):

    @cyclone.web.asynchronous
    def post(self):
    some_validation()
    # Spawn a thread to import the files and leave the post method
    # asynchronous decorator will keep the request open to write the response on, 
    #  once the import is complete
    file_handler.start()  ---- this is a thread that do all the heavy work and in this method we are 
                               closing the request with self.finish

Class file_handler():
     run(self):
         {
          ---do some heavy work, like importing a file
          self.importing_a_large_file()
          self.set_status(status)
          self.write(json_response)
          self.finish()
       
}   

What can be its tornado equivalent method.

I tried various things like adding gencouroutine decorater, change method name to async but nothing seems to work.


Solution

  • Use Python's async def coroutines.

    You can't use regular threading with Tornado, so you'll have to use the run_in_executor method. It will run the code in a separate thread but will allow you to wait for the result without blocking.

    class ABCHandler(tornado.web.RequestHandler):
        async def post(self):
            loop = tornado.ioloop.IOLoop.current()
    
            some_data = await loop.run_in_executor(executor=None, func=blocking_func)
    
           self.write(some_data)
    
    
    # this is a blocking code
    # you don't have to create a separate thread for this
    # because `run_in_executor` will take care of that.
    def blocking_func():
        # do blocking things here
        return some_data