Toggle navigation

What’s new in Tornado 5.0

Mar 5, 2018


  • The focus of this release is improving integration with asyncio. On Python 3, the IOLoop is always a wrapper around the asyncio event loop, and asyncio.Future and asyncio.Task are used instead of their Tornado counterparts. This means that libraries based on asyncio can be mixed relatively seamlessly with those using Tornado. While care has been taken to minimize the disruption from this change, code changes may be required for compatibility with Tornado 5.0, as detailed in the following section.
  • Tornado 5.0 supports Python 2.7.9+ and 3.4+. Python 2.7 and 3.4 are deprecated and support for them will be removed in Tornado 6.0, which will require Python 3.5+.

Backwards-compatibility notes

  • Python 3.3 is no longer supported.
  • Versions of Python 2.7 that predate the ssl module update are no longer supported. (The ssl module was updated in version 2.7.9, although in some distributions the updates are present in builds with a lower version number. Tornado requires ssl.SSLContext, ssl.create_default_context, and ssl.match_hostname)
  • Versions of Python 3.5 prior to 3.5.2 are no longer supported due to a change in the async iterator protocol in that version.
  • The trollius project (asyncio backported to Python 2) is no longer supported.
  • tornado.concurrent.Future is now an alias for asyncio.Future when running on Python 3. This results in a number of minor behavioral changes:

  • io_loop arguments to many Tornado functions have been removed. Use IOLoop.current() instead of passing IOLoop objects explicitly.
  • On Python 3, IOLoop is always a wrapper around the asyncio event loop. IOLoop.configure is effectively removed on Python 3 (for compatibility, it may be called to redundantly specify the asyncio-backed IOLoop)
  • IOLoop.instance is now a deprecated alias for IOLoop.current. Applications that need the cross-thread communication behavior facilitated by IOLoop.instance should use their own global variable instead.

Other notes

  • The futures (concurrent.futures backport) package is now required on Python 2.7.
  • The certifi and backports.ssl-match-hostname packages are no longer required on Python 2.7.
  • Python 3.6 or higher is recommended, because it features more efficient garbage collection of asyncio.Future objects.



  • On Python 3, uses __main__.__spec to more reliably reconstruct the original command line and avoid modifying PYTHONPATH.
  • The io_loop argument to tornado.autoreload.start has been removed.



  • Improved debug logging on Python 3.
  • The time_info response attribute now includes appconnect in addition to other measurements.
  • Closing a CurlAsyncHTTPClient now breaks circular references that could delay garbage collection.
  • The io_loop argument to the CurlAsyncHTTPClient constructor has been removed.


  • tornado.gen.TimeoutError is now an alias for tornado.util.TimeoutError.
  • Leak detection for Futures created by this module now attributes them to their proper caller instead of the coroutine machinery.
  • Several circular references that could delay garbage collection have been broken up.
  • On Python 3, asyncio.Task is used instead of the Tornado coroutine runner. This improves compatibility with some asyncio libraries and adds support for cancellation.
  • The io_loop arguments to YieldFuture and with_timeout have been removed.



  • It is now possible for a client to reuse a connection after sending a chunked request.
  • If a client sends a malformed request, the server now responds with a 400 error instead of simply closing the connection.
  • Content-Length and Transfer-Encoding headers are no longer sent with 1xx or 204 responses (this was already true of 304 responses).
  • When closing a connection to a HTTP/1.1 client, the Connection: close header is sent with the response.
  • The io_loop argument to the HTTPServer constructor has been removed.
  • If more than one X-Scheme or X-Forwarded-Proto header is present, only the last is used.




  • The io_loop argument to the IOStream constructor has been removed.
  • New method BaseIOStream.read_into provides a minimal-copy alternative to BaseIOStream.read_bytes.
  • BaseIOStream.write is now much more efficient for very large amounts of data.
  • Fixed some cases in which IOStream.error could be inaccurate.
  • Writing a memoryview can no longer result in “BufferError: Existing exports of data: object cannot be re-sized”.


  • As a side effect of the Future changes, waiters are always notified asynchronously with respect to Condition.notify.



  • Duplicate option names are now detected properly whether they use hyphens or underscores.






  • A default 404 response is now generated if no delegate is found for a request.




  • The io_loop argument to the TCPServer constructor has been removed.
  • TCPServer no longer logs EBADF errors during shutdown.


  • The deprecated tornado.testing.get_unused_port and tornado.testing.LogTrapTestCase have been removed.
  • AsyncHTTPTestCase.fetch now supports absolute URLs.
  • AsyncHTTPTestCase.fetch now connects to instead of localhost to be more robust against faulty ipv6 configurations.



  • RequestHandler.set_status no longer requires that the given status code appear in http.client.responses.
  • It is no longer allowed to send a body with 1xx or 204 responses.
  • Exception handling now breaks up reference cycles that could delay garbage collection.
  • RedirectHandler now copies any query arguments from the request to the redirect location.
  • If both If-None-Match and If-Modified-Since headers are present in a request to StaticFileHandler, the latter is now ignored.


  • The C accelerator now operates on multiple bytes at a time to improve performance.
  • Requests with invalid websocket headers now get a response with status code 400 instead of a closed connection.
  • WebSocketHandler.write_message now raises WebSocketClosedError if the connection closes while the write is in progress.
  • The io_loop argument to websocket_connect has been removed.