response = http_client.fetch(url)
return response.body
-.. testoutput::
- :hide:
-
And here is the same function rewritten asynchronously as a native coroutine:
.. testcode::
response = await http_client.fetch(url)
return response.body
-.. testoutput::
- :hide:
-
Or for compatibility with older versions of Python, using the `tornado.gen` module:
.. testcode::
fetch_future.add_done_callback(on_fetch)
return my_future
-.. testoutput::
- :hide:
-
Notice that the coroutine returns its `.Future` before the fetch is
done. This is what makes coroutines *asynchronous*.
for url in urls})
# responses is a dict {url: HTTPResponse}
-.. testoutput::
- :hide:
-
In decorated coroutines, it is possible to ``yield`` the list or dict directly::
@gen.coroutine
fetch_future = convert_yielded(self.fetch_next_chunk())
await self.flush()
-.. testoutput::
- :hide:
-
This is a little easier to do with decorated coroutines, because they
start immediately when called:
fetch_future = self.fetch_next_chunk()
yield self.flush()
-.. testoutput::
- :hide:
-
Looping
^^^^^^^
if __name__ == '__main__':
asyncio.run(main())
-.. testoutput::
- :hide:
-
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).
await asyncio.Event().wait()
asyncio.run(post_fork_main())
-.. testoutput::
- :hide:
-
This is another 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
else:
self.write("Your cookie was set!")
-.. testoutput::
- :hide:
-
Cookies are not secure and can easily be modified by clients. If you
need to set cookies to, e.g., identify the currently logged in user,
you need to sign your cookies to prevent forgery. Tornado supports
(r"/", MainHandler),
], cookie_secret="__TODO:_GENERATE_YOUR_OWN_RANDOM_VALUE_HERE__")
-.. testoutput::
- :hide:
-
Signed cookies contain the encoded value of the cookie in addition to a
timestamp and an `HMAC <http://en.wikipedia.org/wiki/HMAC>`_ signature.
If the cookie is old or if the signature doesn't match,
else:
self.write("Your cookie was set!")
-.. testoutput::
- :hide:
-
Tornado's signed cookies guarantee integrity but not confidentiality.
That is, the cookie cannot be modified but its contents can be seen by the
user. The ``cookie_secret`` is a symmetric key and must be kept secret --
(r"/login", LoginHandler),
], cookie_secret="__TODO:_GENERATE_YOUR_OWN_RANDOM_VALUE_HERE__")
-.. testoutput::
- :hide:
-
You can require that the user be logged in using the `Python
decorator <http://www.python.org/dev/peps/pep-0318/>`_
`tornado.web.authenticated`. If a request goes to a method with this
(r"/login", LoginHandler),
], **settings)
-.. testoutput::
- :hide:
-
If you decorate ``post()`` methods with the ``authenticated``
decorator, and the user is not logged in, the server will send a
``403`` response. The ``@authenticated`` decorator is simply
response_type='code',
extra_params={'approval_prompt': 'auto'})
-.. testoutput::
- :hide:
-
See the `tornado.auth` module documentation for more details.
.. _xsrf:
(r"/login", LoginHandler),
], **settings)
-.. testoutput::
- :hide:
-
If ``xsrf_cookies`` is set, the Tornado web application will set the
``_xsrf`` cookie for all users and reject all ``POST``, ``PUT``, and
``DELETE`` requests that do not contain a correct ``_xsrf`` value. If
if __name__ == "__main__":
asyncio.run(main())
-.. testoutput::
- :hide:
-
The ``main`` coroutine
~~~~~~~~~~~~~~~~~~~~~~
self.set_header("Content-Type", "text/plain")
self.write("You wrote " + self.get_body_argument("message"))
-.. testoutput::
- :hide:
-
Since the HTML form encoding is ambiguous as to whether an argument is
a single value or a list with one element, `.RequestHandler` has
distinct methods to allow the application to indicate whether or not
self.write("Fetched " + str(len(json["entries"])) + " entries "
"from the FriendFeed API")
-.. testoutput::
- :hide:
-
For a more advanced asynchronous example, take a look at the `chat
example application
<https://github.com/tornadoweb/tornado/tree/stable/demos/chat>`_, which
items = ["Item 1", "Item 2", "Item 3"]
self.render("template.html", title="My title", items=items)
-.. testoutput::
- :hide:
-
Tornado templates support *control statements* and *expressions*.
Control statements are surrounded by ``{%`` and ``%}``, e.g.
``{% if len(items) > 2 %}``. Expressions are surrounded by ``{{`` and
return None
return self.current_user.prefs["locale"]
-.. testoutput::
- :hide:
-
If ``get_user_locale`` returns ``None``, we fall back on the
``Accept-Language`` header.
response_type='code',
extra_params={'approval_prompt': 'auto'})
-.. testoutput::
- :hide:
-
"""
import base64
return
self.finish("Posted a message!")
- .. testoutput::
- :hide:
-
.. versionadded:: 4.3
.. versionchanged::: 6.0
else:
await self.authorize_redirect()
- .. testoutput::
- :hide:
-
The user object returned by `~OAuthMixin.get_authenticated_user`
includes the attributes ``username``, ``name``, ``access_token``,
and all of the custom Twitter user attributes described at
return
self.finish("Posted a message!")
- .. testoutput::
- :hide:
-
.. versionchanged:: 6.0
The ``callback`` argument was removed. Use the returned
response_type='code',
extra_params={'approval_prompt': 'auto'})
- .. testoutput::
- :hide:
-
.. versionchanged:: 6.0
The ``callback`` argument was removed. Use the returned awaitable object instead.
client_id=self.settings["facebook_api_key"],
extra_params={"scope": "user_posts"})
- .. testoutput::
- :hide:
-
This method returns a dictionary which may contain the following fields:
* ``access_token``, a string which may be passed to `facebook_request`
return
self.finish("Posted a message!")
- .. testoutput::
- :hide:
-
The given path is relative to ``self._FACEBOOK_BASE_URL``,
by default "https://graph.facebook.com".
do_something_with_response(response)
self.render("template.html")
-.. testoutput::
- :hide:
-
Asynchronous functions in Tornado return an ``Awaitable`` or `.Future`;
yielding this object returns its result.
response3 = response_dict['response3']
response4 = response_dict['response4']
-.. testoutput::
- :hide:
-
If ``tornado.platform.twisted`` is imported, it is also possible to
yield Twisted's ``Deferred`` objects. See the `convert_yielded`
function to extend this mechanism.
if __name__ == "__main__":
asyncio.run(main())
- .. testoutput::
- :hide:
-
Most applications should not attempt to construct an `IOLoop` directly,
and instead initialize the `asyncio` event loop and use `IOLoop.current()`.
In some cases, such as in test frameworks when initializing an `IOLoop`
if __name__ == '__main__':
asyncio.run(main())
- .. testoutput::
- :hide:
-
"""
def __init__(self, socket: socket.socket, *args: Any, **kwargs: Any) -> None:
if __name__ == "__main__":
asyncio.run(main())
-.. testoutput::
- :hide:
-
-
See the :doc:`guide` for additional information.
Thread-safety notes
def on_close(self):
print("WebSocket closed")
- .. testoutput::
- :hide:
-
WebSockets are not standard HTTP connections. The "handshake" is
HTTP, but after the handshake, the protocol is
message-based. Consequently, most of the Tornado HTTP facilities
sphinx-build -q -E -n -W -b html . {envtmpdir}/html
# Ensure that everything is either documented or ignored in conf.py
sphinx-build -q -E -n -W -b coverage . {envtmpdir}/coverage
- # Run the doctests. No -W for doctests because that disallows tests
- # with empty output.
- sphinx-build -q -E -n -b doctest . {envtmpdir}/doctest
+ # Run the doctests
+ sphinx-build -q -E -n -W -b doctest . {envtmpdir}/doctest
[testenv:lint]
commands =