user's guide for more on blocking and asynchronous functions.
-My code is asynchronous, but it's not running in parallel in two browser tabs.
-------------------------------------------------------------------------------
+My code is asynchronous. Why is it not running in parallel in two browser tabs?
+-------------------------------------------------------------------------------
Even when a handler is asynchronous and non-blocking, it can be surprisingly
tricky to verify this. Browsers will recognize that you are trying to
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
+is required. Examples in the Tornado documentation will generally use
the native form.
Translation between the two forms is generally straightforward::
# special exception. # Return normally
raise gen.Return(b) return b
-Other differences between the two forms of coroutine are:
-
-- Native coroutines are generally faster.
-- Native coroutines can use ``async for`` and ``async with``
- statements which make some patterns much simpler.
-- Native coroutines do not run at all unless you ``await`` or
- ``yield`` them. 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 use ``await`` or ``yield`` so that
- any exceptions have somewhere to go.
-- Decorated coroutines have additional integration with the
- `concurrent.futures` package, allowing the result of
- ``executor.submit`` to be yielded directly. For native coroutines,
- use `.IOLoop.run_in_executor` instead.
-- Decorated coroutines support some shorthand for waiting on multiple
- objects by yielding a list or dict. Use `tornado.gen.multi` to do
- this in native coroutines.
-- Decorated coroutines can support integration with other packages
- including Twisted via a registry of conversion functions.
- To access this functionality in native coroutines, use
- `tornado.gen.convert_yielded`.
-- Decorated coroutines always return a `.Future` object. Native
- coroutines return an *awaitable* object that is not a `.Future`. In
- Tornado the two are mostly interchangeable.
+Other differences between the two forms of coroutine are outlined below.
+
+- Native coroutines:
+
+ - are generally faster.
+ - can use ``async for`` and ``async with``
+ statements which make some patterns much simpler.
+ - do not run at all unless you ``await`` or
+ ``yield`` them. 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 use ``await`` or ``yield`` so that
+ any exceptions have somewhere to go.
+
+- Decorated coroutines:
+
+ - have additional integration with the
+ `concurrent.futures` package, allowing the result of
+ ``executor.submit`` to be yielded directly. For native coroutines,
+ use `.IOLoop.run_in_executor` instead.
+ - support some shorthand for waiting on multiple
+ objects by yielding a list or dict. Use `tornado.gen.multi` to 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, use
+ `tornado.gen.convert_yielded`.
+ - always return a `.Future` object. Native
+ coroutines return an *awaitable* object that is not a `.Future`. In
+ Tornado the two are mostly interchangeable.
How it works
~~~~~~~~~~~~
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
-the Tornado's web framework and HTTP server together.
+Tornado's web framework and HTTP server together.
Configure your operating system or process manager to run this program to
start the server. Please note that it may be necessary to increase the number
of open files per process (to avoid "Too many open files"-Error).
-To raise this limit (setting it to 50000 for example) you can use the ulimit command,
-modify /etc/security/limits.conf or setting ``minfds`` in your supervisord config.
+To raise this limit (setting it to 50000 for example) you can use the
+``ulimit`` command, modify ``/etc/security/limits.conf`` or set
+``minfds`` in your `supervisord <http://www.supervisord.org>`_ config.
Processes and ports
~~~~~~~~~~~~~~~~~~~
This is the easiest way to start multiple processes and have them all
share the same port, although it has some limitations. First, each
-child process will have its own IOLoop, so it is important that
-nothing touch the global IOLoop instance (even indirectly) before the
+child process will have its own ``IOLoop``, so it is important that
+nothing touches the global ``IOLoop`` instance (even indirectly) before the
fork. Second, it is difficult to do zero-downtime updates in this model.
Finally, since all the processes share the same port it is more difficult
to monitor them individually.
Running behind a load balancer
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-When running behind a load balancer like nginx, it is recommended to
-pass ``xheaders=True`` to the `.HTTPServer` constructor. This will tell
-Tornado to use headers like ``X-Real-IP`` to get the user's IP address
-instead of attributing all traffic to the balancer's IP address.
+When running behind a load balancer like `nginx <http://nginx.net/>`_,
+it is recommended to pass ``xheaders=True`` to the `.HTTPServer` constructor.
+This will tell Tornado to use headers like ``X-Real-IP`` to get the user's
+IP address instead of attributing all traffic to the balancer's IP address.
This is a barebones nginx config file that is structurally similar to
the one we use at FriendFeed. It assumes nginx and the Tornado servers
], **settings)
This setting will automatically make all requests that start with
-``/static/`` serve from that static directory, e.g.,
+``/static/`` serve from that static directory, e.g.
``http://localhost:8888/static/foo.png`` will serve the file
``foo.png`` from the specified static directory. We also automatically
serve ``/robots.txt`` and ``/favicon.ico`` from the static directory
server down in a way that debug mode cannot currently recover from.
* ``compiled_template_cache=False``: Templates will not be cached.
* ``static_hash_cache=False``: Static file hashes (used by the
- ``static_url`` function) will not be cached
+ ``static_url`` function) will not be cached.
* ``serve_traceback=True``: When an exception in a `.RequestHandler`
is not caught, an error page including a stack trace will be
generated.
necessary. On every request, the following sequence of calls takes
place:
-1. A new `.RequestHandler` object is created on each request
+1. A new `.RequestHandler` object is created on each request.
2. `~.RequestHandler.initialize()` is called with the initialization
arguments from the `.Application` configuration. ``initialize``
should typically just save the arguments passed into member
disconnects; applications may choose to detect this case and halt
further processing. Note that there is no guarantee that a closed
connection can be detected promptly.
-- `~.RequestHandler.get_current_user` - see :ref:`user-authentication`
+- `~.RequestHandler.get_current_user` - see :ref:`user-authentication`.
- `~.RequestHandler.get_user_locale` - returns `.Locale` object to use
- for the current user
+ for the current user.
- `~.RequestHandler.set_default_headers` - may be used to set
additional headers on the response (such as a custom ``Server``
- header)
+ header).
Error Handling
~~~~~~~~~~~~~~
considered permanent. The default value of ``permanent`` is
``False``, which generates a ``302 Found`` HTTP response code and is
appropriate for things like redirecting users after successful
-``POST`` requests. If ``permanent`` is true, the ``301 Moved
+``POST`` requests. If ``permanent`` is ``True``, the ``301 Moved
Permanently`` HTTP response code is used, which is useful for
e.g. redirecting to a canonical URL for a page in an SEO-friendly
manner.
:hide:
Tornado templates support *control statements* and *expressions*.
-Control statements are surrounded by ``{%`` and ``%}``, e.g.,
+Control statements are surrounded by ``{%`` and ``%}``, e.g.
``{% if len(items) > 2 %}``. Expressions are surrounded by ``{{`` and
-``}}``, e.g., ``{{ items[0] }}``.
+``}}``, e.g. ``{{ items[0] }}``.
Control statements more or less map exactly to Python statements. We
support ``if``, ``for``, ``while``, and ``try``, all of which are
Expressions can be any Python expression, including function calls.
Template code is executed in a namespace that includes the following
-objects and functions (Note that this list applies to templates
+objects and functions. (Note that this list applies to templates
rendered using `.RequestHandler.render` and
`~.RequestHandler.render_string`. If you're using the
`tornado.template` module directly outside of a `.RequestHandler` many
additional escaping. Additionally, either care must be taken to always
use double quotes and `.xhtml_escape` in HTML attributes that may contain
untrusted content, or a separate escaping function must be used for
-attributes (see e.g. http://wonko.com/post/html-escaping)
+attributes (see e.g.
+`this blog post <http://wonko.com/post/html-escaping>`_).
Internationalization
~~~~~~~~~~~~~~~~~~~~
simple ``.csv`` format. An application will generally call either
`tornado.locale.load_translations` or
`tornado.locale.load_gettext_translations` once at startup; see those
-methods for more details on the supported formats..
+methods for more details on the supported formats.
You can get the list of supported locales in your application with
`tornado.locale.get_supported_locales()`. The user's locale is chosen
For example, if you are implementing a blog, and you want to have blog
entries appear on both the blog home page and on each blog entry page,
you can make an ``Entry`` module to render them on both pages. First,
-create a Python module for your UI modules, e.g., ``uimodules.py``::
+create a Python module for your UI modules, e.g. ``uimodules.py``::
class Entry(tornado.web.UIModule):
def render(self, entry, show_comments=False):
-----------
* Current version: |version| (`download from PyPI <https://pypi.python.org/pypi/tornado>`_, :doc:`release notes <releases>`)
-* `Source (github) <https://github.com/tornadoweb/tornado>`_
+* `Source (GitHub) <https://github.com/tornadoweb/tornado>`_
* Mailing lists: `discussion <http://groups.google.com/group/python-tornado>`_ and `announcements <http://groups.google.com/group/python-tornado-announce>`_
* `Stack Overflow <http://stackoverflow.com/questions/tagged/tornado>`_
* `Wiki <https://github.com/tornadoweb/tornado/wiki/Links>`_
The arguments to these methods come from the `.URLSpec`: Any
capturing groups in the regular expression become arguments to the
HTTP verb methods (keyword arguments if the group is named,
- positional arguments if its unnamed).
+ positional arguments if it's unnamed).
To support a method not on this list, override the class variable
``SUPPORTED_METHODS``::
Application configuration
- -----------------------------
+ -------------------------
+
.. autoclass:: Application(handlers: List[Union[Rule, Tuple]] = None, default_host: str = None, transforms: List[Type[OutputTransform]] = None, **settings)
.. attribute:: settings
`RequestHandler` object). The default implementation
writes to the `logging` module's root logger. May also be
customized by overriding `Application.log_request`.
- * ``serve_traceback``: If true, the default error page
+ * ``serve_traceback``: If ``True``, the default error page
will include the traceback of the error. This option is new in
Tornado 3.2; previously this functionality was controlled by
the ``debug`` setting.
* ``login_url``: The `authenticated` decorator will redirect
to this url if the user is not logged in. Can be further
customized by overriding `RequestHandler.get_login_url`
- * ``xsrf_cookies``: If true, :ref:`xsrf` will be enabled.
+ * ``xsrf_cookies``: If ``True``, :ref:`xsrf` will be enabled.
* ``xsrf_cookie_version``: Controls the version of new XSRF
cookies produced by this server. Should generally be left
at the default (which will always be the highest supported
* In the OAuth section of the page, select Create New Client ID.
* Set the Redirect URI to point to your auth handler
* Copy the "Client secret" and "Client ID" to the application settings as
- {"google_oauth": {"key": CLIENT_ID, "secret": CLIENT_SECRET}}
+ ``{"google_oauth": {"key": CLIENT_ID, "secret": CLIENT_SECRET}}``
.. versionadded:: 3.2
"""
) -> None:
"""Set the given ``value`` as the `Future`'s result, if not cancelled.
- Avoids asyncio.InvalidStateError when calling set_result() on
+ Avoids ``asyncio.InvalidStateError`` when calling ``set_result()`` on
a cancelled `asyncio.Future`.
.. versionadded:: 5.0
If the Future is already canceled, logs the exception instead. If
this logging is not desired, the caller should explicitly check
- the state of the Future and call Future.set_exception instead of
+ the state of the Future and call ``Future.set_exception`` instead of
this wrapper.
- Avoids asyncio.InvalidStateError when calling set_exception() on
+ Avoids ``asyncio.InvalidStateError`` when calling ``set_exception()`` on
a cancelled `asyncio.Future`.
.. versionadded:: 6.0
.. versionchanged:: 6.0
If the future is already cancelled, this function is a no-op.
- (previously asyncio.InvalidStateError would be raised)
+ (previously ``asyncio.InvalidStateError`` would be raised)
"""
if exc_info[1] is None:
``simple_httpclient`` (unsupported by ``curl_httpclient``).
Overrides ``validate_cert``, ``ca_certs``, ``client_key``,
and ``client_cert``.
- :arg bool allow_ipv6: Use IPv6 when available? Default is true.
+ :arg bool allow_ipv6: Use IPv6 when available? Default is True.
:arg bool expect_100_continue: If true, send the
``Expect: 100-continue`` header and wait for a continue response
before sending the request body. Only supported with
- simple_httpclient.
+ ``simple_httpclient``.
.. note::
Attributes:
- * request: HTTPRequest object
+ * ``request``: HTTPRequest object
- * code: numeric HTTP status code, e.g. 200 or 404
+ * ``code``: numeric HTTP status code, e.g. 200 or 404
- * reason: human-readable reason phrase describing the status code
+ * ``reason``: human-readable reason phrase describing the status code
- * headers: `tornado.httputil.HTTPHeaders` object
+ * ``headers``: `tornado.httputil.HTTPHeaders` object
- * effective_url: final location of the resource after following any
+ * ``effective_url``: final location of the resource after following any
redirects
- * buffer: ``cStringIO`` object for response body
+ * ``buffer``: ``cStringIO`` object for response body
- * body: response body as bytes (created on demand from ``self.buffer``)
+ * ``body``: response body as bytes (created on demand from ``self.buffer``)
- * error: Exception object, if any
+ * ``error``: Exception object, if any
- * request_time: seconds from request start to finish. Includes all network
- operations from DNS resolution to receiving the last byte of data.
- Does not include time spent in the queue (due to the ``max_clients`` option).
- If redirects were followed, only includes the final request.
+ * ``request_time``: seconds from request start to finish. Includes all
+ network operations from DNS resolution to receiving the last byte of
+ data. Does not include time spent in the queue (due to the
+ ``max_clients`` option). If redirects were followed, only includes
+ the final request.
- * start_time: Time at which the HTTP operation started, based on `time.time`
- (not the monotonic clock used by `.IOLoop.time`). May be ``None`` if the request
- timed out while in the queue.
+ * ``start_time``: Time at which the HTTP operation started, based on
+ `time.time` (not the monotonic clock used by `.IOLoop.time`). May
+ be ``None`` if the request timed out while in the queue.
- * time_info: dictionary of diagnostic timing information from the request.
- Available data are subject to change, but currently uses timings
+ * ``time_info``: dictionary of diagnostic timing information from the
+ request. Available data are subject to change, but currently uses timings
available from http://curl.haxx.se/libcurl/c/curl_easy_getinfo.html,
plus ``queue``, which is the delay (if any) introduced by waiting for
a slot under `AsyncHTTPClient`'s ``max_clients`` setting.
self._timeout = None
def is_running(self) -> bool:
- """Return True if this `.PeriodicCallback` has been started.
+ """Returns ``True`` if this `.PeriodicCallback` has been started.
.. versionadded:: 4.1
"""
self._write_buffer = None # type: ignore
def reading(self) -> bool:
- """Returns true if we are currently reading from the stream."""
+ """Returns ``True`` if we are currently reading from the stream."""
return self._read_future is not None
def writing(self) -> bool:
- """Returns true if we are currently writing to the stream."""
+ """Returns ``True`` if we are currently writing to the stream."""
return bool(self._write_buffer)
def closed(self) -> bool:
- """Returns true if the stream has been closed."""
+ """Returns ``True`` if the stream has been closed."""
return self._closed
def set_nodelay(self, value: bool) -> None:
self.io_loop.update_handler(self.fileno(), self._state)
def _is_connreset(self, exc: BaseException) -> bool:
- """Return true if exc is ECONNRESET or equivalent.
+ """Return ``True`` if exc is ECONNRESET or equivalent.
May be overridden in subclasses.
"""
except socket.error as e:
# Sometimes setsockopt will fail if the socket is closed
# at the wrong time. This can happen with HTTPServer
- # resetting the value to false between requests.
+ # resetting the value to ``False`` between requests.
if e.errno != errno.EINVAL and not self._is_connreset(e):
raise
future_set_result_unless_cancelled(future, self)
def _verify_cert(self, peercert: Any) -> bool:
- """Returns True if peercert is valid according to the configured
+ """Returns ``True`` if peercert is valid according to the configured
validation mode and hostname.
The ssl handshake already tested the certificate for a valid
def is_valid_ip(ip: str) -> bool:
- """Returns true if the given string is a well-formed IP address.
+ """Returns ``True`` if the given string is a well-formed IP address.
Supports IPv4 and IPv6.
"""
``timeout`` keyword argument or globally with the
``ASYNC_TEST_TIMEOUT`` environment variable.
- If ``condition`` is not None, the `.IOLoop` will be restarted
- after `stop()` until ``condition()`` returns true.
+ If ``condition`` is not ``None``, the `.IOLoop` will be restarted
+ after `stop()` until ``condition()`` returns ``True``.
.. versionchanged:: 3.1
Added the ``ASYNC_TEST_TIMEOUT`` environment variable.
"""Convenience method to synchronously fetch a URL.
The given path will be appended to the local server's host and
- port. Any additional kwargs will be passed directly to
+ port. Any additional keyword arguments will be passed directly to
`.AsyncHTTPClient.fetch` (and so could be used to pass
``method="POST"``, ``body="..."``, etc).
If the path begins with http:// or https://, it will be treated as a
full URL and will be fetched as-is.
- If ``raise_error`` is True, a `tornado.httpclient.HTTPError` will
+ If ``raise_error`` is ``True``, a `tornado.httpclient.HTTPError` will
be raised if the response code is not 200. This is the same behavior
as the ``raise_error`` argument to `.AsyncHTTPClient.fetch`, but
- the default is False here (it's True in `.AsyncHTTPClient`) because
- tests often need to deal with non-200 response codes.
+ the default is ``False`` here (it's ``True`` in `.AsyncHTTPClient`)
+ because tests often need to deal with non-200 response codes.
.. versionchanged:: 5.0
Added support for absolute URLs.
Useful to make tests of error conditions less noisy, while still
leaving unexpected log entries visible. *Not thread safe.*
- The attribute ``logged_stack`` is set to true if any exception
+ The attribute ``logged_stack`` is set to ``True`` if any exception
stack trace was logged.
Usage::
"""A simple test runner.
This test runner is essentially equivalent to `unittest.main` from
- the standard library, but adds support for tornado-style option
+ the standard library, but adds support for Tornado-style option
parsing and log formatting. It is *not* necessary to use this
`main` function to run tests using `AsyncTestCase`; these tests
are self-contained and can run with any test runner.
python -m tornado.testing tornado.test.web_test
- See the standard library unittest module for ways in which tests can
- be specified.
+ See the standard library ``unittest`` module for ways in which
+ tests can be specified.
Projects with many tests may wish to define a test script like
``tornado/test/runtests.py``. This script should define a method
.. versionchanged:: 5.0
This function produces no output of its own; only that produced
- by the `unittest` module (Previously it would add a PASS or FAIL
+ by the `unittest` module (previously it would add a PASS or FAIL
log message).
"""
from tornado.options import define, options, parse_command_line
def import_object(name: str) -> Any:
"""Imports an object by name.
- import_object('x') is equivalent to 'import x'.
- import_object('x.y.z') is equivalent to 'from x.y import z'.
+ ``import_object('x')`` is equivalent to ``import x``.
+ ``import_object('x.y.z')`` is equivalent to ``from x.y import z``.
>>> import tornado.escape
>>> import_object('tornado.escape') is tornado.escape
"""Returns the base class of a configurable hierarchy.
This will normally return the class in which it is defined.
- (which is *not* necessarily the same as the cls classmethod parameter).
+ (which is *not* necessarily the same as the ``cls`` classmethod
+ parameter).
+
"""
raise NotImplementedError()
def timedelta_to_seconds(td):
# type: (datetime.timedelta) -> float
- """Equivalent to td.total_seconds() (introduced in python 2.7)."""
+ """Equivalent to ``td.total_seconds()`` (introduced in Python 2.7)."""
return td.total_seconds()
initialize = _initialize # type: Callable[..., None]
"""Hook for subclass initialization. Called for each request.
- A dictionary passed as the third argument of a url spec will be
- supplied as keyword arguments to initialize().
+ A dictionary passed as the third argument of a ``URLSpec`` will be
+ supplied as keyword arguments to ``initialize()``.
Example::
If the given chunk is a dictionary, we write it as JSON and set
the Content-Type of the response to be ``application/json``.
(if you want to send JSON as a different ``Content-Type``, call
- set_header *after* calling write()).
+ ``set_header`` *after* calling ``write()``).
Note that lists are not converted to JSON because of a potential
cross-site security vulnerability. All JSON output should be
implement WebSockets support this header, and non-browser
clients do not have the same cross-site security concerns).
- Should return True to accept the request or False to reject it.
- By default, rejects all requests with an origin on a host other
- than this one.
+ Should return ``True`` to accept the request or ``False`` to
+ reject it. By default, rejects all requests with an origin on
+ a host other than this one.
This is a security protection against cross site scripting attacks on
browsers, since WebSockets are allowed to bypass the usual same-origin
for more.
To accept all cross-origin traffic (which was the default prior to
- Tornado 4.0), simply override this method to always return true::
+ Tornado 4.0), simply override this method to always return ``True``::
def check_origin(self, origin):
return True
)
def is_closing(self) -> bool:
- """Return true if this connection is closing.
+ """Return ``True`` if this connection is closing.
The connection is considered closing if either side has
initiated its closing handshake or if the stream has been