File: demos/tcpecho/README.md
TCP echo demo
This demo shows how to use Tornado's asynchronous TCP client and
server by implementing handle_stream as a coroutine.
To run the server:
$ python server.pyThe client will send the message given with the --message option
(which defaults to "ping"), wait for a response, then quit. To run:
$ python client.py --message="your message here"Alternatively, you can interactively send messages to the echo server
with a telnet client. For example:
$ telnet localhost 9888
Trying ::1...
Connected to localhost.
Escape character is '^]'.
ping
pingFile: docs/guide/async.rst
Asynchronous and non-Blocking I/O
Real-time web features require a long-lived mostly-idle connection per
user. In a traditional synchronous web server, this implies devoting
one thread to each user, which can be very expensive.
To minimize the cost of concurrent connections, Tornado uses a
single-threaded event loop. This means that all application code
should aim to be asynchronous and non-blocking because only one
operation can be active at a time.
The terms asynchronous and non-blocking are closely related and are
often used interchangeably, but they are not quite the same thing.
Blocking
A function **blocks** when it waits for something to happen before
returning. A function may block for many reasons: network I/O, disk
I/O, mutexes, etc. In fact, *every* function blocks, at least a
little bit, while it is running and using the CPU (for an extreme
example that demonstrates why CPU blocking must be taken as seriously
as other kinds of blocking, consider password hashing functions like
`bcrypt <http://bcrypt.sourceforge.net/>`_, which by design use
hundreds of milliseconds of CPU time, far more than a typical network
or disk access).
A function can be blocking in some respects and non-blocking in
others. In the context of Tornado we generally talk about
blocking in the context of network I/O, although all kinds of blocking
are to be minimized.
AsynchronousAn asynchronous function returns before it is finished, and
generally causes some work to happen in the background before
triggering some future action in the application (as opposed to normal
synchronous functions, which do everything they are going to do
before returning). There are many styles of asynchronous interfaces:
- Callback argument
- Return a placeholder (
.Future,Promise,Deferred) - Deliver to a queue
- Callback registry (e.g. POSIX signals)
Regardless of which type of interface is used, asynchronous functions
by definition interact differently with their callers; there is no
free way to make a synchronous function asynchronous in a way that is
transparent to its callers (systems like gevent <http://www.gevent.org>_ use lightweight threads to offer performance
comparable to asynchronous systems, but they do not actually make
things asynchronous).
Asynchronous operations in Tornado generally return placeholder
objects (Futures), with the exception of some low-level components
like the .IOLoop that use callbacks. Futures are usually
transformed into their result with the await or yield
keywords.
Examples
Here is a sample synchronous function:
.. testcode::
from tornado.httpclient import HTTPClient
def synchronous_fetch(url):
http_client = HTTPClient()
response = http_client.fetch(url)
return response.body
And here is the same function rewritten asynchronously as a native coroutine:
.. testcode::
from tornado.httpclient import AsyncHTTPClient
async def asynchronous_fetch(url):
http_client = AsyncHTTPClient()
response = await http_client.fetch(url)
return response.body
Or for compatibility with older versions of Python, using the `tornado.gen` module:
.. testcode::
from tornado.httpclient import AsyncHTTPClient
from tornado import gen
@gen.coroutine
def async_fetch_gen(url):
http_client = AsyncHTTPClient()
response = yield http_client.fetch(url)
raise gen.Return(response.body)
Coroutines are a little magical, but what they do internally is something like this:
.. testcode::
from tornado.concurrent import Future
def async_fetch_manual(url):
http_client = AsyncHTTPClient()
my_future = Future()
fetch_future = http_client.fetch(url)
def on_fetch(f):
my_future.set_result(f.result().body)
fetch_future.add_done_callback(on_fetch)
return my_future
Notice that the coroutine returns its `.Future` before the fetch is
done. This is what makes coroutines *asynchronous*.
Anything you can do with coroutines you can also do by passing
callback objects around, but coroutines provide an important
simplification by letting you organize your code in the same way you
would if it were synchronous. This is especially important for error
handling, since ``try``/``except`` blocks work as you would expect in
coroutines while this is difficult to achieve with callbacks.
Coroutines will be discussed in depth in the next section of this
guide.
---
## File: docs/guide/coroutines.rst
Coroutines
==========
.. testsetup::
from tornado import gen
**Coroutines** are the recommended way to write asynchronous code in
Tornado. Coroutines use the Python ``await`` keyword to
suspend and resume execution instead of a chain of callbacks
(cooperative lightweight threads as seen in frameworks like `gevent
<http://www.gevent.org>`_ 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
<https://glyph.twistedmatrix.com/2014/02/unyielding.html>`_ to reason
about by reducing the number of places where a context switch can
happen.
Example::
async def fetch_coroutine(url):
http_client = AsyncHTTPClient()
response = await http_client.fetch(url)
return response.body
.. _native_coroutines:
Native vs decorated coroutinesPython 3.5 introduced the async and await keywords (functions
using these keywords are also called "native coroutines"). For
compatibility with older versions of Python, you can use "decorated"
or "yield-based" coroutines using the tornado.gen.coroutine
decorator.
Native coroutines are the recommended form whenever possible. Only use
decorated coroutines when compatibility with older versions of Python
is required. Examples in the Tornado documentation will generally use
the native form.
Translation between the two forms is generally straightforward::
# Decorated: # Native:
# Normal function declaration
# with decorator # "async def" keywords
@gen.coroutine
def a(): async def a():
# "yield" all async funcs # "await" all async funcs
b = yield c() b = await c()
# "return" and "yield"
# cannot be mixed in
# Python 2, so raise a
# special exception. # Return normally
raise gen.Return(b) return bOther differences between the two forms of coroutine are outlined below.
Native coroutines:
- are generally faster.
- can use
async forandasync with
statements which make some patterns much simpler. - do not run at all unless you
awaitoryieldthem. Decorated coroutines can start running "in the
background" as soon as they are called. Note that for both kinds of
coroutines it is important to useawaitoryieldso that
any exceptions have somewhere to go.
Decorated coroutines:
- have additional integration with the
concurrent.futurespackage, allowing the result ofexecutor.submitto be yielded directly. For native coroutines,
use.IOLoop.run_in_executorinstead. - support some shorthand for waiting on multiple
objects by yielding a list or dict. Usetornado.gen.multito do
this in native coroutines. - can support integration with other packages
including Twisted via a registry of conversion functions.
To access this functionality in native coroutines, usetornado.gen.convert_yielded. - always return a
.Futureobject. Native
coroutines return an awaitable object that is not a.Future. In
Tornado the two are mostly interchangeable.
- have additional integration with the
How it works
This section explains the operation of decorated coroutines. Native
coroutines are conceptually similar, but a little more complicated
because of the extra integration with the Python runtime.
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.Runner
def run(self):
# send(x) makes the current yield return x.
# It returns when the next yield is reached
future = self.gen.send(self.next)
def callback(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.
How to call a coroutineCoroutines do not raise exceptions in the normal way: any exception
they raise will be trapped in the awaitable object until it is
yielded. This means it is important to call coroutines in the right
way, or you may have errors that go unnoticed::
async def divide(x, y):
return x / y
def bad_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 await or 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")::
async def good_call():
# await will unwrap the object returned by divide() and raise
# the exception.
await divide(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 async def (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))Coroutine patterns
Calling blocking functions
^^^^^^^^^^^^^^^^^^^^^^^^^^
The simplest way to call a blocking function from a coroutine is to
use `.IOLoop.run_in_executor`, which returns
``Futures`` that are compatible with coroutines::
async def call_blocking():
await IOLoop.current().run_in_executor(None, blocking_func, args)
Parallelism
^^^^^^^^^^^
The `.multi` function accepts lists and dicts whose values are
``Futures``, and waits for all of those ``Futures`` in parallel:
.. testcode::
from tornado.gen import multi
async def parallel_fetch(url1, url2):
resp1, resp2 = await multi([http_client.fetch(url1),
http_client.fetch(url2)])
async def parallel_fetch_many(urls):
responses = await multi ([http_client.fetch(url) for url in urls])
# responses is a list of HTTPResponses in the same order
async def parallel_fetch_dict(urls):
responses = await multi({url: http_client.fetch(url)
for url in urls})
# responses is a dict {url: HTTPResponse}
In decorated coroutines, it is possible to ``yield`` the list or dict directly::
@gen.coroutine
def parallel_fetch_decorated(url1, url2):
resp1, resp2 = yield [http_client.fetch(url1),
http_client.fetch(url2)]
Interleaving
^^^^^^^^^^^^
Sometimes it is useful to save a `.Future` instead of yielding it
immediately, so you can start another operation before waiting.
.. testcode::
from tornado.gen import convert_yielded
async def get(self):
# convert_yielded() starts the native coroutine in the background.
# This is equivalent to asyncio.ensure_future() (both work in Tornado).
fetch_future = convert_yielded(self.fetch_next_chunk())
while True:
chunk = await fetch_future
if chunk is None: break
self.write(chunk)
fetch_future = convert_yielded(self.fetch_next_chunk())
await self.flush()
This is a little easier to do with decorated coroutines, because they
start immediately when called:
.. testcode::
@gen.coroutine
def get(self):
fetch_future = self.fetch_next_chunk()
while True:
chunk = yield fetch_future
if chunk is None: break
self.write(chunk)
fetch_future = self.fetch_next_chunk()
yield self.flush()
Looping
^^^^^^^
In native coroutines, ``async for`` can be used. In older versions of
Python, looping is tricky with coroutines since there is no way 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 <https://motor.readthedocs.io/en/stable/>`_::
import motor
db = motor.MotorClient().test
@gen.coroutine
def loop_example(collection):
cursor = db.collection.find()
while (yield cursor.fetch_next):
doc = cursor.next_object()
Running in the background
^^^^^^^^^^^^^^^^^^^^^^^^^
As an alternative to `.PeriodicCallback`, a
coroutine can contain a ``while True:`` loop and use
`tornado.gen.sleep`::
async def minute_loop():
while True:
await do_something()
await gen.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::
async def minute_loop2():
while True:
nxt = gen.sleep(60) # Start the clock.
await do_something() # Run while the clock is ticking.
await nxt # Wait for the timer to run out.
---
## File: docs/guide/intro.rst
Introduction
------------
`Tornado <http://www.tornadoweb.org>`_ is a Python web framework and
asynchronous networking library, originally developed at `FriendFeed
<https://en.wikipedia.org/wiki/FriendFeed>`_. By using non-blocking network I/O, Tornado
can scale to tens of thousands of open connections, making it ideal for
`long polling <http://en.wikipedia.org/wiki/Push_technology#Long_polling>`_,
`WebSockets <http://en.wikipedia.org/wiki/WebSocket>`_, and other
applications that require a long-lived connection to each user.
Tornado can be roughly divided into three major components:
* A web framework (including `.RequestHandler` which is subclassed to
create web applications, and various supporting classes).
* Client- and server-side implementations of HTTP (`.HTTPServer` and
`.AsyncHTTPClient`).
* An asynchronous networking library including the classes `.IOLoop`
and `.IOStream`, which serve as the building blocks for the HTTP
components and can also be used to implement other protocols.
The Tornado web framework and HTTP server together offer a full-stack
alternative to `WSGI <http://www.python.org/dev/peps/pep-3333/>`_.
While it is possible to use the Tornado HTTP server as a container for
other WSGI frameworks (`.WSGIContainer`), this combination has
limitations and to take full advantage of Tornado you will need to use
Tornado's web framework and HTTP server together.
---
## File: docs/guide/queues.rst
:class:`~tornado.queues.Queue` example - a concurrent web spider
================================================================
.. currentmodule:: tornado.queues
Tornado's `tornado.queues` module (and the very similar ``Queue`` classes in
`asyncio`) implements an asynchronous producer / consumer pattern for
coroutines, analogous to the pattern implemented for threads by the Python
standard library's `queue` module.
A coroutine that yields `Queue.get` pauses until there is an item in the queue.
If the queue has a maximum size set, a coroutine that yields `Queue.put` pauses
until there is room for another item.
A `~Queue` maintains a count of unfinished tasks, which begins at zero.
`~Queue.put` increments the count; `~Queue.task_done` decrements it.
In the web-spider example here, the queue begins containing only base_url. When
a worker fetches a page it parses the links and puts new ones in the queue,
then calls `~Queue.task_done` to decrement the counter once. Eventually, a
worker fetches a page whose URLs have all been seen before, and there is also
no work left in the queue. Thus that worker's call to `~Queue.task_done`
decrements the counter to zero. The main coroutine, which is waiting for
`~Queue.join`, is unpaused and finishes.
.. literalinclude:: ../../demos/webspider/webspider.py