Привет, жители Хабра! Это Леша Жиряков из МТС Диджитал. В прошлый раз я опубликовал пост Polars vs Pandas, а сегодня поговорим о FastAPI и Litestar — фреймворках для микросервисов. У каждого из них свои сильные стороны, так какой выбрать для своего проекта? Давайте разбираться. Ниже — о плюсах и минусах каждого, сравнение производительности и примеры валидации.
Что за фреймворки
FastAPI создан Себастьяном Рамиресом в 2018 году. Инструмент быстро завоевал популярность благодаря простоте, использованию аннотаций типов и интеграции с OpenAPI. На GitHub у FastAPI больше 79 тыс. звезд, это один из самых популярных инструментов для создания веб-приложений.
Особенности: интеграция «из коробки» с OpenAPI, автоматическая генерация документации через Swagger UI и ReDoc, встроенная валидация и сериализация данных с помощью Pydantic, тесная связь с аннотациями типов Python для упрощения разработки.
Количество звезд на GitHub: 80 тыс.
Открытых Issues: всего 51.
Версия: 0.115.7.
Год релиза: 2018.
Merge Requests (MRs): FastAPI поддерживается основным разработчиком Себастьяном Рамиресом. Сообщество принимает участие в переводе документации, улучшении тестов и обновлении библиотек.
Litestar — современный ASGI-фреймворк (Asynchronous Server Gateway Interface), ориентированный на высокую производительность и минимализм. На GitHub у него около 5,9 тыс. звезд, которые он собрал за последние три года (первый релиз вышел в декабре 2021 года). Разработчики ценят контроль и прозрачность кода. Благодаря лаконичному подходу и гибкости Litestar предоставляет мощные инструменты для создания API, включая валидацию данных, внедрение зависимостей и интеграцию с ORM. Отличный выбор для производительных приложений.
Особенности: минималистичный подход, высокая производительность, гибкость настройки, отсутствие автоматизированной «магии» (когда что-то указано не явно).
Количество звезд на GitHub: 5,9 тыс.
Открытых Issues: 181.
Версия: 2.14.0.
Год релиза: 2021.
Merge Requests (MRs): принимаются комьюнити.
Чем один отличается от другого
FastAPI: автоматизация и «магия»
FastAPI основан на Starlette и ориентирован на программистов, которые стремятся сократить время разработки за счет автоматизации. Одна из главных его особенностей — использование аннотаций типов Python для автоматической валидации данных, генерации OpenAPI-документации и описания входных и выходных данных. Этот подход делает процесс интуитивно понятным: разработчику достаточно использовать стандартные типы Python или Pydantic, чтобы FastAPI автоматически создал спецификацию API и реализовал валидацию данных.
Пример валидации в FastAPI
Допустим, у нас есть проект с файлом main.py, который содержит такой код:
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
async def index() -> str:
return "Hello, world!"
@app.get("/books/{book_id}")
async def get_book(book_id: int) -> dict[str, int]:
return {"book_id": book_id}
И для аргумента book_id метода get_book указан тип данных int.
Обратимся к адресу http://127.0.0.1:8000/books/1 и получим такой вывод:
{"book_id":1}
А теперь попробуем вместо целого числа указать вещественное и использовать путь http://127.0.0.1:8000/books/0.001.
Выводится ошибка:
{"detail":[{"type":"int_parsing","loc":["path","book_id"],"msg":"Input should be a valid integer, unable to parse string as an integer","input":"0.001"}]}
При открытии API по ссылке http://127.0.0.1:8000/docs можно увидеть, какой тип данных у аргумента ожидает метод:
Работа упрощается, отпадает необходимость вручную прописывать схемы данных, а еще снижается вероятность ошибок, связанных с неправильной обработкой данных. Автоматизация делает FastAPI удобным инструментом для проектов, где важны скорость, стандартизация API и упрощение взаимодействия с клиентами.
Вот только у этой простоты есть обратная сторона: многие процессы проходят внутри фреймворка. Например, генерация документации и валидация данных происходят автоматически, а возможности кастомизации ограничены. Это делает FastAPI менее гибким для решений, требующих точной настройки или модификации внутренней логики. Если возникает нестандартная ситуация или ошибка, разработчику может быть сложно разобраться во внутренней логике FastAPI. К тому же «магия» автоматизации иногда приводит к дополнительным сложностям при интеграции с другими инструментами, если они требуют точного контроля над процессами.
Еще FastAPI известен своими ограничениями в области отладки. Многие функции фреймворка выполняются «за кулисами», так что диагностика ошибок может занять больше времени. Это особенно заметно в масштабных проектах, где прозрачность кода имеет критическое значение. Несмотря на эти ограничения, FastAPI остается мощным инструментом, особенно для разработчиков, которые ценят быстрое внедрение и стандартизацию API.
Плюсы:
автоматическая генерация документации OpenAPI;
удобная работа с аннотациями типов Python;
активная экосистема и множество готовых решений.
Минусы:
большая часть логики скрыта за «магией», то есть нет необходимости прямого вмешательства разработчика.
Litestar: минимализм и прозрачность
Litestar противоположен FastAPI в своем подходе: он дает разработчикам больший контроль над процессами. Фреймворк ориентирован на минимализм, предлагает только базовые инструменты для создания API. Тем не менее Litestar поддерживает автоматическую генерацию документации в формате OpenAPI и встроенную валидацию данных через Pydantic или attrs. При этом есть гибкость в выборе дополнительных инструментов и библиотек. Такой подход позволяет избежать избыточности и обеспечивает прозрачность кода.
Пример валидации в Litestar — акцент на явность
Теперь рассмотрим валидацию в Litestar. Немного отредактируем код (изменим импорты и добавим :int после book_id в описании декоратора get). Получим вот что:
from litestar import Litestar, get
@get("/")
async def index() -> str:
return "Hello, world!"
@get("/books/{book_id:int}")
async def get_book(book_id: int) -> dict[str, int]:
return {"book_id": book_id}
app = Litestar([index, get_book])
Открываем страницу по ссылке http://127.0.0.1:8000/books/1 и получаем вывод:
{"book_id":1}
http://127.0.0.1:8000/books/0.001
Теперь указываем другой тип данных и видим ошибку:
{"status_code":404,"detail":"Not Found"}
Можно заметить, что в FastAPI информация об ошибке была более подробной и понятной, чем в Litestar.
В Litestar целых четыре вида документации, у каждой свой путь после хоста:
/schema (ReDoc)
/schema/swagger (Swagger UI)
/schema/elements (Stoplight Elements)
/schema/rapidoc (RapiDoc)
Чтобы открыть старый добрый Swagger, нужно будет перейти по ссылке http://127.0.0.1:8000/schema/swagger. Вместо /docs, как в FastAPI, тут используется /schema/swagger/.
Как у Litestar работает роутинг
Роутинг в Litestar кардинально отличается от его коллег по цеху — FastAPI и Starlett. Если в двух последних они реализованы при помощи перебора и рекурсивной функции, то в Litestar — на основе radix tree.
Сложность операций в дереве О(k), где k — это количество битов максимально длинного пути.
Из файла routing.py библиотеки Starlette:
for route in self.routes:
match, child_scope = route.matches(redirect_scope)
Из файла core.py библиотеки Litestar:
class _RouteTree(Tree):
def __init__(self, routes: list[HTTPRoute | ASGIRoute | WebSocketRoute]) -> None:
super().__init__("", hide_root=True)
self._routes = routes
self._build()
Если говорить о плюсах использования дерева, то основным будет то, что мы уходим от линейного роста. Есть и минус — парсинг параметров из url стал медленнее.
Роутинг указывается при создании приложения. Аргументу route_handlers по ключу передается список со всеми путями. Например, в коде выше — только путь add_user:
app = Litestar(route_handlers=[add_user])
Еще есть возможность динамической регистрации путей при помощи метода register:
from litestar import Litestar, get
@get()
def root_handler() -> None: …
app = Litestar(route_handlers=[root_handler])
@get("/another-path")
def another_path_handler() -> None: …
app.register(another_path_handler)
Важно добавить, что динамическая регистрация усложняет понимание кода и должна использоваться только в случае крайней необходимости.
Можно сказать, роутинг у Litestar направлен на высокую производительность и гибкость. Поддерживаются динамические маршруты, параметры запросов и вложенные роуты. Все это позволяет легко организовать сложную структуру URL. Применяются оптимизированные алгоритмы маршрутизации, которые обеспечивают минимальные задержки при обработке запросов. Благодаря асинхронной архитектуре роутинг эффективно масштабируется, а это делает его подходящим для высоконагруженных веб-приложений.
DTO
Ещеоднаособенность Litestar — слойDTO (Data Transfer Object).
Да, приходится писать чуть больше кода. Но мы ведь уходим от «магии», которая есть в FastAPI. В примере ниже можно увидеть, как указывается выходной DTO. В декораторе post добавляется return_dto=Info:
from dataclasses import dataclass
from typing import Annotated
from litestar import post, Litestar
from litestar.params import Body
@dataclass
class User:
id: int
name: str
@dataclass
class Info:
name: str
@post(path="/", return_dto=Info)
async def add_user(data: Annotated[User, Body(title="Hello", description="New user.")]) -> Info:
return data
app = Litestar(route_handlers=[add_user])
Litestar и его гибкость
Основной плюс Litestar — гибкость. Вы можете настроить каждый аспект приложения — от маршрутизации до обработки запросов — без необходимости подстраиваться под встроенные механизмы. Это особенно важно для проектов с уникальными требованиями, где стандартные решения могут быть недостаточны. Но такой подход требует от разработчиков больше времени и навыков: они самостоятельно настраивают все процессы.
Litestar лучше всего подходит для тех, кто готов вложить дополнительные усилия ради максимального контроля и производительности, сохраняя при этом доступ к важным инструментам. Например, автоматической генерации документации и валидации данных. Этот фреймворк — выбор для опытных разработчиков, ценящих минимализм и управляемость.
Плюсы:
прозрачная архитектура и минимализм;
полный контроль над процессами;
хорошо подходит для проектов, где важны высокая производительность и отсутствие лишнего кода.
Минусы:
меньше интеграций и готовых решений;
потребуется больше усилий для настройки и разработки.
Сравнение производительности
Согласно данным из репозитория litestar-org/api-performance-tests, были проведены тесты, сравнивающие производительность различных ASGI-фреймворков, включая FastAPI и Litestar. В этих тестах использовался инструмент bombardier для оценки производительности в различных сценариях: синхронная и асинхронная обработка запросов, сериализация данных в JSON, отправка разных объемов данных. Результаты показали, что Litestar демонстрирует более высокую производительность по сравнению с FastAPI в большинстве тестов.
Нужно больше тестов? Они есть! Вот несколько графиков по результатам бенчмарков из доклада «Жизнь после FastAPI»:
На первом графике — результаты тестирования производительности трех фреймворков для работы с веб-приложениями на Python: FastAPI, Starlette и Litestar. Основная метрика — количество запросов в секунду (RPS, requests per second). Производительность тестировалась на обработке данных разного размера — от 100 байт до 1 Мб.
Litestar показал наивысшую производительность в большинстве тестов, особенно при увеличении размера данных. FastAPI оказался самым медленным, особенно в синхронном режиме. Ну и Starlette занимает промежуточную позицию, но ближе к FastAPI.
На втором графике — результаты теста производительности обработки JSON-данных различного размера, от 1 Кб до 1 Мб. Метрика — количество запросов в секунду (RPS, requests per second).
Litestar снова показал лучшие результаты, особенно при работе с небольшими JSON-файлами (1 Кб и 10 Кб) — как в синхронном, так и в асинхронном режиме. FastAPI значительно отстает по числу запросов в секунду. Это заметнее всего на больших объемах данных (500 Кб и 1 Мб). Ну и Starlette дал средние результаты — лучше, чем FastAPI, но хуже, чем Litestar.
Важный фактор, влияющий на результат, — архитектурный подход каждого фреймворка. Litestar разработан с акцентом на минимализм и эффективность, а значит, может обрабатывать запросы с меньшими накладными расходами. FastAPI больше направлен на быструю разработку и использует dependency injection.
Еще различия FastAPI и Litestar
Посмотрим на версии фреймворков. Мажорная версия FastAPI начинается с 0, а это говорит вот о чем: гарантий совместимости нет и в проде ее можно использовать на свой страх и риск. В то же время на другой стороне берега у Litestar — версия уже 2. Это отражает готовность к использованию в продакшне и обратную совместимость между минорными версиями.
Каждому проекту нужно развиваться, и у open-source-решения есть преимущество — комьюнити. FastAPI открыт для изменений, однако MR’ы сообщества обычно принимаются только когда добавляется перевод, редактируются файлы .MD, улучшаются тесты или обновляются версии библиотек. Изменения, которые касаются глубокой функциональности, вносит только основатель фреймворка — Себастьян Рамирес. Надеюсь, там, где он живет сейчас, все хорошо с автобусами. А вот в Litestar сообществу позволяют свободно вносить свою лепту в улучшение проекта.
Как уже упоминалось выше, документация FastAPI генерируется в Swagger. У Litestar тоже есть такая возможность, но тут можно использовать ReDoc, Stoplight Elements, RapiDoc и так далее, на любой вкус и цвет.
Litestar уходит от «магии», которая есть в FastAPI, и переходит на светлую сторону явности. В нем тоже есть фабрики для работы со слоем DTO: PydanticDTO, DataclassDTO, MsgSpecDTO, SqlAlchemyDTO.
О возможностях Litestar на бис: кэширование ответов, observability (мониторинг, отслеживание, prometheus, opentelemetry), работа с веб-сокетами, авторизация и аутентификация, сессии и события, Polyfactory и многое другое.
Как выбирать
При выборе между FastAPI и Litestar нужно учитывать специфику проекта и требования к производительности и функциональности. А еще — готовность команды к работе с тем или иным инструментом. Оба фреймворка имеют свои сильные стороны, и оптимальный выбор зависит от конкретных задач и приоритетов разработки.
Если вы цените скорость разработки, автоматизацию и встроенные инструменты, выбирайте FastAPI. Тут богатый набор возможностей «из коробки». Это ускоряет разработку и снижает количество ошибок, особенно в проектах, где нужна быстрая реализация.
Если же для вас важны производительность, минимализм и контроль над кодом, Litestar станет идеальным выбором. При этом могут потребоваться дополнительные усилия для работы с фреймворком.
Оба фреймворка предлагают мощные инструменты для создания микросервисов, так что стоит попробовать и тот и другой. Кто уже использует Litestar в проде, опишите, как полет?
Комментарии (3)
tokarev
29.01.2025 13:46начали использовать Litestar где-то год назад, в целом надо понимать что фреймворк достаточно молодой, серьезных багов пока не находили, но какие-то мелочи тут и там постоянно (особенно с генерацией документации). Из плюсов - очень просто и быстро принимают пулреквесты, чтобы эти мелочи поправить
twistfire92
минорными