Tornado – асинхронный веб-сервер

онлайн тренер по питону
Онлайн-тренажер Python 3 для начинающих

Теория без воды. Задачи с автоматической проверкой. Подсказки на русском языке. Работает в любом современном браузере.

начать бесплатно

Введение в Tornado

Tornado — это асинхронный веб-сервер и веб-фреймворк на Python, разработанный для обслуживания большого количества одновременных соединений. Он сочетает высокую производительность с гибкой архитектурой и применяется в создании веб-приложений, API-сервисов и систем реального времени с поддержкой WebSocket. Благодаря использованию неблокирующего ввода-вывода и встроенного цикла событий, Tornado особенно хорошо подходит для обработки большого количества клиентов и чатов, стриминга и push-уведомлений.


Особенности и преимущества Tornado

  • Асинхронная архитектура на основе событий

  • Поддержка WebSocket и долгих соединений (long polling)

  • Встроенный HTTP-сервер

  • Обработка тысяч соединений на одном потоке

  • Гибкое маршрутизирование и middleware

  • Совместимость с asyncio (начиная с версии 5.0+)

  • Низкий уровень абстракции — полный контроль над логикой


Установка и структура проекта

Установка Tornado:

bash
pip install tornado

Минимальная структура проекта:

cpp
project/ │ ├── app.py ├── templates/ │ └── index.html └── static/ └── style.css

Запуск простого веб-сервера

Пример базового приложения:

python
import tornado.ioloop import tornado.web class MainHandler(tornado.web.RequestHandler): def get(self): self.write("Привет от Tornado") def make_app(): return tornado.web.Application([ (r"/", MainHandler), ]) if __name__ == "__main__": app = make_app() app.listen(8888) tornado.ioloop.IOLoop.current().start()

Обработка маршрутов и запросов

Добавление URL-маршрутов:

python
(r"/about", AboutHandler), (r"/user/([0-9]+)", UserHandler),

Передача параметров в get(self, id) возможна через регулярные выражения.


Асинхронные обработчики и цикл событий

Асинхронный обработчик:

python
import asyncio class AsyncHandler(tornado.web.RequestHandler): async def get(self): await asyncio.sleep(1) self.write("Асинхронный ответ")

Tornado совместим с async def и использует IOLoop как ядро событийной модели.


Работа с шаблонами HTML

Tornado использует собственный шаблонизатор:

html
<!-- templates/index.html --> <html> <body> <h1>Привет, {{ name }}!</h1> </body> </html>

В обработчике:

python
def get(self): self.render("index.html", name="Торнадо")

Обработка форм и данных POST

Форма:

html
<form action="/submit" method="post"> <input name="name"> <input type="submit"> </form>

Обработчик:

python
def post(self): name = self.get_argument("name") self.write(f"Получено имя: {name}")

Работа с файлами и загрузка данных

Загрузка файла:

python
def post(self): fileinfo = self.request.files["filearg"][0] with open(f"uploads/{fileinfo['filename']}", "wb") as f: f.write(fileinfo["body"])

WebSocket в Tornado

python
import tornado.websocket class EchoWebSocket(tornado.websocket.WebSocketHandler): def open(self): print("WebSocket открыт") def on_message(self, message): self.write_message(f"Получено: {message}") def on_close(self): print("WebSocket закрыт")

Подключение:

python
(r"/ws", EchoWebSocket),

Работа с базой данных (Motor, AsyncPG)

Пример с MongoDB (Motor):

bash
pip install motor
python
import motor.motor_tornado client = motor.motor_tornado.MotorClient("mongodb://localhost:27017") db = client.mydatabase

Асинхронный запрос:

python
async def get(self): document = await db.collection.find_one({}) self.write(document)

Middleware и фильтрация запросов

Через методы prepare() и set_default_headers() можно настроить промежуточную обработку:

python
def prepare(self): if self.request.method not in ["GET", "POST"]: self.set_status(405) self.finish()

Обработка ошибок и логирование

Настройка write_error():

python
def write_error(self, status_code, **kwargs): self.render("error.html", code=status_code)

Логирование:

python
import logging logging.basicConfig(level=logging.INFO)

Безопасность и защита от атак

  • Защита от XSRF: self.check_xsrf_cookie()

  • HTTPS: через ssl_options в app.listen

  • CORS: ручная настройка заголовков

  • Ограничение методов и проверка Content-Type


Развёртывание Tornado-сервера в продакшн

Запуск на определённом IP и порту:

python
app.listen(8000, address="0.0.0.0")

С использованием gunicorn с WSGI-адаптером или через систему supervisor, systemd.


Примеры практического применения Tornado

  • Реализация WebSocket-чатов

  • Push-сервисы и уведомления

  • Панели мониторинга в реальном времени

  • Асинхронные API и микросервисы

  • Веб-интерфейсы для потоковых данных


Часто задаваемые вопросы

Что такое Tornado?

Асинхронный веб-сервер и фреймворк на Python для масштабируемой обработки HTTP-запросов и WebSocket-соединений.

Поддерживает ли Tornado asyncio?

Да, начиная с версии 5.0, Tornado полностью совместим с asyncio.

Чем Tornado отличается от FastAPI или Flask?

Tornado — это низкоуровневый фреймворк с приоритетом на асинхронность и масштабируемость, в отличие от более высокоуровневых FastAPI и Flask.

Есть ли поддержка шаблонов?

Да, Tornado имеет встроенный шаблонизатор.

Подходит ли Tornado для продакшн?

Да, при правильной настройке Tornado способен обслуживать тысячи соединений и применяется в крупных проектах.

Полный справочник по ключевым функциям и структуре фреймворка Tornado для Python

Установка

bash
pip install tornado

Основные особенности Tornado

  • Асинхронная модель на базе asyncio.

  • Высокая производительность и масштабируемость.

  • Поддержка WebSocket "из коробки".

  • Встроенный HTTP-сервер (не требует WSGI).

  • Поддержка маршрутизации, шаблонов и куки.


Основные модули и классы

Компонент Назначение
tornado.web.Application Приложение со списком URL-обработчиков.
tornado.web.RequestHandler Базовый класс для создания контроллеров.
tornado.ioloop.IOLoop Главный цикл событий.
tornado.httpserver.HTTPServer Обёртка для запуска Tornado-сервера.
tornado.websocket.WebSocketHandler Обработчик WebSocket-соединений.

Пример простого HTTP-приложения

python
import tornado.ioloop import tornado.web class MainHandler(tornado.web.RequestHandler): def get(self): self.write("Привет, Tornado!") def make_app(): return tornado.web.Application([ (r"/", MainHandler), ]) if __name__ == "__main__": app = make_app() app.listen(8888) tornado.ioloop.IOLoop.current().start()

Асинхронные обработчики

python
class AsyncHandler(tornado.web.RequestHandler): async def get(self): await some_async_call() self.write("Асинхронный ответ")

Передача данных (GET, POST)

python
class FormHandler(tornado.web.RequestHandler): def post(self): name = self.get_argument("name") self.write(f"Привет, {name}")

Маршруты

Маршруты — список кортежей: (r"/путь", КлассОбработчика)
Поддержка регулярных выражений и параметров:

python
(r"/user/([0-9]+)", UserHandler), (r"/post/(?P<slug>[-\w]+)", PostHandler),

Шаблоны (HTML)

По умолчанию используется собственный шаблонизатор.
Пример файла index.html в templates/:

html
<html> <body> Привет, {{ name }} </body> </html>

В RequestHandler:

python
self.render("index.html", name="Иван")

Для этого в Application указываем:

python
tornado.web.Application([...], template_path="templates")

Работа со статикой

python
tornado.web.Application([...], static_path="static")

Доступ к файлам: http://localhost:8888/static/style.css


Куки и сессии

Метод Описание
self.set_cookie("key", "value") Установка куки.
self.get_cookie("key") Получение куки.
self.clear_cookie("key") Удаление куки.

Обработка ошибок

python
def write_error(self, status_code, **kwargs): self.render("error.html", code=status_code)

WebSocket

python
import tornado.websocket class MyWebSocket(tornado.websocket.WebSocketHandler): def open(self): print("WebSocket открыт") def on_message(self, message): self.write_message(f"Вы отправили: {message}") def on_close(self): print("WebSocket закрыт")

Запуск HTTP/HTTPS сервера

python
import tornado.httpserver app = make_app() server = tornado.httpserver.HTTPServer(app) server.listen(8888) tornado.ioloop.IOLoop.current().start()

Для HTTPS:

python
server = HTTPServer(app, ssl_options={ "certfile": "cert.pem", "keyfile": "key.pem" })

Интеграция с asyncio

python
import asyncio from tornado.platform.asyncio import AsyncIOMainLoop AsyncIOMainLoop().install() asyncio.run(main())

Примеры продвинутого использования

  • Асинхронные HTTP-запросы через tornado.httpclient.AsyncHTTPClient.

  • Обработка форм и загрузка файлов: self.request.files.