How do you understand the ioloop in tornado?

2020-07-24 06:07发布

问题:

I am looking for a way to understand ioloop in tornado, since I read the official doc several times, but can't understand it. Specifically, why it exists.

from tornado.concurrent import Future
from tornado.httpclient import AsyncHTTPClient
from tornado.ioloop import IOLoop
def async_fetch_future():
    http_client = AsyncHTTPClient()
    future = Future()
    fetch_future = http_client.fetch(
        "http://mock.kite.com/text")
    fetch_future.add_done_callback(
        lambda f: future.set_result(f.result()))
    return future

response = IOLoop.current().run_sync(async_fetch_future) 
# why get current IO of this thread? display IO, hard drive IO, or network IO? 
print response.body

I know what is IO, input and output, e.g. read a hard drive, display graph on the screen, get keyboard input. by definition, IOLoop.current() returns the current io loop of this thread.

There are many IO device on my laptop running this python code. Which IO does this IOLoop.current() return? I never heard of IO loop in javascript nodejs.

Furthermore, why do I care this low level thing if I just want to do a database query, read a file?

回答1:

Rather to say it is IOLoop, maybe EventLoop is clearer for you to understand.

IOLoop.current() doesn't really return an IO device but just a pure python event loop which is basically the same as asyncio.get_event_loop() or the underlying event loop in nodejs.

The reason why you need event loop to just do a database query is that you are using event-driven structure to do databse query(In your example, you are doing http request).

Most of time you do not need to care about this low level structure. Instead you just need to use async&await keywords.

Let's say there is a lib which supports asynchronous database access:

async def get_user(user_id):
    user = await async_cursor.execute("select * from user where user_id = %s" % user_id)
    return user

Then you just need to use this function in your handler:

class YourHandler(tornado.web.RequestHandler):

    async def get():
        user = await get_user(self.get_cookie("user_id"))
        if user is None:
            return self.finish("No such user")
        return self.finish("Your are %s" % user.user_name)


回答2:

I never heard of IO loop in javascript nodejs.

In node.js, the equivalent concept is the event loop. The node event loop is mostly invisible because all programs use it - it's what's running in between your callbacks.

In Python, most programs don't use an event loop, so when you want one, you have to run it yourself. This can be a Tornado IOLoop, a Twisted Reactor, or an asyncio event loop (all of these are specific types of event loops).

Tornado's IOLoop is perhaps confusingly named - it doesn't do any IO directly. Instead, it coordinates all the different IO (mainly network IO) that may be happening in the program. It may help you to think of it as an "event loop" or "callback runner".