Coroutines are the recommended way to write asynchronous code in
Tornado. Coroutines use the Python yield keyword to suspend and
resume execution instead of a chain of callbacks (cooperative
lightweight threads as seen in frameworks like gevent are sometimes called coroutines as well, but
in Tornado all coroutines use explicit context switches and are called
as asynchronous functions).

Coroutines are almost as simple as synchronous code, but without the
expense of a thread. They also make concurrency easier to reason
about by reducing the number of places where a context switch can
happen.

Example:

fromtornadoimportgen@gen.coroutinedeffetch_coroutine(url):http_client=AsyncHTTPClient()response=yieldhttp_client.fetch(url)# In Python versions prior to 3.3, returning a value from# a generator is not allowed and you must use# raise gen.Return(response.body)# instead.returnresponse.body

Python 3.5 introduces the async and await keywords (functions
using these keywords are also called “native coroutines”). Starting in
Tornado 4.3, you can use them in place of yield-based coroutines.
Simply use asyncdeffoo() in place of a function definition with
the @gen.coroutine decorator, and await in place of yield. The
rest of this document still uses the yield style for compatibility
with older versions of Python, but async and await will run
faster when they are available:

The await keyword is less versatile than the yield keyword.
For example, in a yield-based coroutine you can yield a list of
Futures, while in a native coroutine you must wrap the list in
tornado.gen.multi. You can also use tornado.gen.convert_yielded
to convert anything that would work with yield into a form that
will work with await.

While native coroutines are not visibly tied to a particular framework
(i.e. they do not use a decorator like tornado.gen.coroutine or
asyncio.coroutine), not all coroutines are compatible with each
other. There is a coroutine runner which is selected by the first
coroutine to be called, and then shared by all coroutines which are
called directly with await. The Tornado coroutine runner is
designed to be versatile and accept awaitable objects from any
framework; other coroutine runners may be more limited (for example,
the asyncio coroutine runner does not accept coroutines from other
frameworks). For this reason, it is recommended to use the Tornado
coroutine runner for any application which combines multiple
frameworks. To call a coroutine using the Tornado runner from within a
coroutine that is already using the asyncio runner, use the
tornado.platform.asyncio.to_asyncio_future adapter.

A function containing yield is a generator. All generators
are asynchronous; when called they return a generator object instead
of running to completion. The @gen.coroutine decorator
communicates with the generator via the yield expressions, and
with the coroutine’s caller by returning a Future.

Here is a simplified version of the coroutine decorator’s inner loop:

# Simplified inner loop of tornado.gen.Runnerdefrun(self):# send(x) makes the current yield return x.# It returns when the next yield is reachedfuture=self.gen.send(self.next)defcallback(f):self.next=f.result()self.run()future.add_done_callback(callback)

The decorator receives a Future from the generator, waits (without
blocking) for that Future to complete, then “unwraps” the Future
and sends the result back into the generator as the result of the
yield expression. Most asynchronous code never touches the Future
class directly except to immediately pass the Future returned by
an asynchronous function to a yield expression.

Coroutines do not raise exceptions in the normal way: any exception
they raise will be trapped in the Future until it is yielded. This
means it is important to call coroutines in the right way, or you may
have errors that go unnoticed:

@gen.coroutinedefdivide(x,y):returnx/ydefbad_call():# This should raise a ZeroDivisionError, but it won't because# the coroutine is called incorrectly.divide(1,0)

In nearly all cases, any function that calls a coroutine must be a
coroutine itself, and use the yield keyword in the call. When you
are overriding a method defined in a superclass, consult the
documentation to see if coroutines are allowed (the documentation
should say that the method “may be a coroutine” or “may return a
Future”):

@gen.coroutinedefgood_call():# yield will unwrap the Future returned by divide() and raise# the exception.yielddivide(1,0)

Sometimes you may want to “fire and forget” a coroutine without waiting
for its result. In this case it is recommended to use IOLoop.spawn_callback,
which makes the IOLoop responsible for the call. If it fails,
the IOLoop will log a stack trace:

# The IOLoop will catch the exception and print a stack trace in# the logs. Note that this doesn't look like a normal call, since# we pass the function object to be called by the IOLoop.IOLoop.current().spawn_callback(divide,1,0)

Using IOLoop.spawn_callback in this way is recommended for
functions using @gen.coroutine, but it is required for functions
using asyncdef (otherwise the coroutine runner will not start).

Finally, at the top level of a program, if the IOLoop is not yet
running, you can start the IOLoop, run the coroutine, and then
stop the IOLoop with the IOLoop.run_sync method. This is often
used to start the main function of a batch-oriented program:

# run_sync() doesn't take arguments, so we must wrap the# call in a lambda.IOLoop.current().run_sync(lambda:divide(1,0))

To interact with asynchronous code that uses callbacks instead of
Future, wrap the call in a Task. This will add the callback
argument for you and return a Future which you can yield:

@gen.coroutinedefcall_task():# Note that there are no parens on some_function.# This will be translated by Task into# some_function(other_args, callback=callback)yieldgen.Task(some_function,other_args)

The coroutine decorator recognizes lists and dicts whose values are
Futures, and waits for all of those Futures in parallel:

@gen.coroutinedefparallel_fetch(url1,url2):resp1,resp2=yield[http_client.fetch(url1),http_client.fetch(url2)]@gen.coroutinedefparallel_fetch_many(urls):responses=yield[http_client.fetch(url)forurlinurls]# responses is a list of HTTPResponses in the same order@gen.coroutinedefparallel_fetch_dict(urls):responses=yield{url:http_client.fetch(url)forurlinurls}# responses is a dict {url: HTTPResponse}

This pattern is most usable with @gen.coroutine. If
fetch_next_chunk() uses asyncdef, then it must be called as
fetch_future=tornado.gen.convert_yielded(self.fetch_next_chunk()) to start the
background processing.

Looping is tricky with coroutines since there is no way in Python
to yield on every iteration of a for or while loop and
capture the result of the yield. Instead, you’ll need to separate
the loop condition from accessing the results, as in this example
from Motor:

@gen.coroutinedefminute_loop():whileTrue:yielddo_something()yieldgen.sleep(60)# Coroutines that loop forever are generally started with# spawn_callback().IOLoop.current().spawn_callback(minute_loop)

Sometimes a more complicated loop may be desirable. For example, the
previous loop runs every 60+N seconds, where N is the running
time of do_something(). To run exactly every 60 seconds, use the
interleaving pattern from above:

@gen.coroutinedefminute_loop2():whileTrue:nxt=gen.sleep(60)# Start the clock.yielddo_something()# Run while the clock is ticking.yieldnxt# Wait for the timer to run out.