Python Blog Series IV- Python Tornado — A non-blocking web server

CauseCode Technologies
2 min readMay 18, 2018

If a server is non-blocking, it means that the process can handle more than one requests at the same time and the request doesn’t have to wait for any I/O or other event to occur.

Traditional web server were synchronous and assigned each thread per user which were very costly, hence a single-threaded event loop can be used by Tornado to make the the code non-blocking and asynchronous as a single operation can be active at one time.

Tornado’s ioloop is the wrapper of asyncio.

Advantages of using non-blocking web server

  • Easy to scale for large number of connections.
  • More appropriate for real time systems where lot of background execution is required.
  • Client doesn’t have to wait for the handler to complete its execution to get response.

Following are the useful decorators related to asynchronous execution.

Tornado.web.asynchronous (method)

If the function returns before its execution is finished and performs some background execution, then the function is asynchronous. In that case, the function can be decorated with asynchronous decorator.

This decorator is used when the callback approach is used for asynchronization.

Method must be executing something asynchronous in order to make the decorator meaningful.

When the decorator is used and if the request is not completed when the handler returns, we need to explicitly call self.finish() in order to complete the request.

import tornadoclass Handler(tornado.web.RequestHandler):
@tornado.web.asynchronous
def get(self):
http_client = httpclient.AsyncHTTPClient()
http.fetch("https://www.google.co.in/search?q=python", callback=self.on_callback)
def on_callback(self, response):
self.write("In callback method")
self.finish()

Note: Adding the generator will not make the function asynchronous, but it tells the framework about the same.

tornado.gen.coroutine(method)

Recommended way to write asynchronous code in Tornado is by using coroutines. Instead of using chains of callbacks, it uses Python yield to resume and suspend the execution.

Have a look at the following example:

from tornado import gen@gen.coroutine
def fetch_image(img_url):
http_client = AsyncHTTPClient()
response = yield http_client.fetch(img_url)
return response.body

async and await keywords

Introduced from Python 3.5 and compatible from Tornado 4.3. Async and await can be used in places of yield based coroutines.

In addition to the decorator, @gen.coroutine can be replaced with the function definition as async def function_name()and yield can be replaced with await.

async def fetch_image(img_url):
http_client = AsyncHTTPClient()
response = await http_client.fetch(img_url)
return response.body

That’s it. Hope you find it useful, thanks!

--

--

CauseCode Technologies

Helping startups/enterprises innovate faster using LeanStartup and Agile principles. Digital Health | Product Development| Analytics & more