neoeahit
neoeahit

Reputation: 1799

Explaining python tornado async

So I have been investigating into how to write async code, and i have come up with the code below:

I have the following two questions:

  1. How can we assume this code is async? We are just meant to rely on the fact that using the gen module makes it async( of course we need to write async modules for the gen coroutine)
  2. Why does tornado incorporate one main thread? can we have a main thread linking to a pool of thread which links to another pool of threads? This question is more towards what do we achieve with one main thread?
from tornado import gen
import tornado.web
import tornado.ioloop
import motor

class MainHandler(tornado.web.RequestHandler):
  @tornado.web.asynchronous
  @gen.coroutine
  def get(self):
    post = yield db.user.find_one()
    print post
    self.write(post['name'])

handlers=[(
(r'/', MainHandler)
)]

db = motor.MotorClient().example

if __name__ == '__main__':
  application = tornado.web.Application(handlers,debug=True)
  application.listen(8888)
  tornado.ioloop.IOLoop.instance().start()

Upvotes: 2

Views: 2772

Answers (2)

Merlin
Merlin

Reputation: 25669

The best way to write async code is to write classes/functions. Then call the class/function. This method allows the event loop to handle the callback. Look at code sample below, there is function created, and then the function is used as callback. This (agian) is allowing the Event Loop do a callback in async way.

from tornado.httpclient import AsyncHTTPClient

def asynchronous_fetch(url, callback):
    http_client = AsyncHTTPClient()
    def handle_response(response):
        callback(response.body)
    http_client.fetch(url, callback=handle_response)

Upvotes: 0

Ben Darnell
Ben Darnell

Reputation: 22154

Asynchronousness is a property of the interface; using @gen.coroutine is sufficient to make this handler asynchronous because it changes the interface (to return a Future. As an aside, you don't need to use the @asynchronous decorator here; since Tornado 3.1 the @coroutine decorator alone has been enough). Furthermore, since Motor returns Futures to be yielded, we know that it is also asynchronous.

Blocking is a property of the implementation; what you're really asking is how we know whether this handler is non-blocking. This, unfortunately is a trickier question. We know from Motor's documentation that it is designed and intended to be non-blocking, but there is no simple way to verify that it is in fact fully non-blocking. There is more discussion of what it means to be asynchronous and non-blocking at http://www.tornadoweb.org/en/stable/guide/async.html.

Tornado uses a single main thread because a single-threaded non-blocking system can achieve higher performance than a threaded one (especially when considering the limitations imposed by the python GIL), and the complexity of making everything asynchronous is offset by the fact that you don't generally need to worry about thread-safety issues.

Upvotes: 4

Related Questions