Альтернативы, источники вдохновения и сравнения¶
Что вдохновило FastAPI, сравнение с альтернативами и чему он у них научился.
Введение¶
FastAPI не существовал бы без предыдущих работ других людей.
Было создано множество инструментов, которые вдохновили на его появление.
Я несколько лет избегал создания нового фреймворка. Сначала пытался закрыть все возможности, которые сейчас предоставляет FastAPI, с помощью множества разных фреймворков, плагинов и инструментов.
Но в какой-то момент не осталось другого варианта, кроме как создать что-то, что включает все эти возможности, взяв лучшие идеи из прежних инструментов и совместив их максимально удачным образом, используя возможности языка, которых прежде не было (аннотации типов в Python 3.6+).
Предшествующие инструменты¶
Django¶
Это самый популярный Python-фреймворк, ему широко доверяют. Он используется для построения систем вроде Instagram.
Он относительно тесно связан с реляционными базами данных (например, MySQL или PostgreSQL), поэтому использовать NoSQL-базу данных (например, Couchbase, MongoDB, Cassandra и т. п.) в качестве основного хранилища не очень просто.
Он был создан для генерации HTML на бэкенде, а не для создания API, используемых современным фронтендом (например, React, Vue.js и Angular) или другими системами (например, устройствами IoT), которые с ним общаются.
Django REST Framework¶
Django REST Framework был создан как гибкий набор инструментов для построения веб-API поверх Django, чтобы улучшить его возможности в части API.
Он используется многими компаниями, включая Mozilla, Red Hat и Eventbrite.
Это был один из первых примеров автоматической документации API, и именно эта идея одной из первых вдохновила на «поиск» FastAPI.
Заметка
Django REST Framework был создан Томом Кристи. Он же создал Starlette и Uvicorn, на которых основан FastAPI.
Вдохновило FastAPI на
Наличие пользовательского веб-интерфейса с автоматической документацией API.
Flask¶
Flask — это «микрофреймворк», он не включает интеграции с базами данных и многие другие вещи, которые в Django идут «из коробки».
Эта простота и гибкость позволяет, например, использовать NoSQL-базы в качестве основной системы хранения данных.
Он очень прост, его относительно легко интуитивно освоить, хотя местами документация довольно техническая.
Его также часто используют для приложений, которым не нужна база данных, управление пользователями или многие другие функции, предварительно встроенные в Django. Хотя многие из этих возможностей можно добавить плагинами.
Такое разбиение на части и то, что это «микрофреймворк», который можно расширять ровно под нужды, — ключевая особенность, которую хотелось сохранить.
С учётом простоты Flask он казался хорошим вариантом для создания API. Следующим было найти «Django REST Framework» для Flask.
Вдохновило FastAPI на
Быть микро-фреймворком. Облегчить комбинирование необходимых инструментов и компонентов.
Иметь простую и удобную систему маршрутизации.
Requests¶
FastAPI на самом деле не альтернатива Requests. Их области применения очень различны.
Обычно Requests используют даже внутри приложения FastAPI.
И всё же FastAPI во многом вдохновлялся Requests.
Requests — это библиотека для взаимодействия с API (как клиент), а FastAPI — библиотека для создания API (как сервер).
Они, в каком-то смысле, находятся на противоположных концах и дополняют друг друга.
Requests имеет очень простой и понятный дизайн, им очень легко пользоваться, есть разумные значения по умолчанию. И при этом он очень мощный и настраиваемый.
Именно поэтому на официальном сайте сказано:
Requests — один из самых загружаемых Python-пакетов всех времён
Пользоваться им очень просто. Например, чтобы сделать запрос GET
, вы бы написали:
response = requests.get("http://example.com/some/url")
Соответствующая в FastAPI API-операция пути могла бы выглядеть так:
@app.get("/some/url")
def read_url():
return {"message": "Hello World"}
Посмотрите, насколько похожи requests.get(...)
и @app.get(...)
.
Вдохновило FastAPI на
- Иметь простой и понятный API.
- Использовать названия HTTP-методов (операций) напрямую, простым и интуитивным образом.
- Иметь разумные значения по умолчанию, но и мощные настройки.
Swagger / OpenAPI¶
Главной возможностью, которую хотелось взять из Django REST Framework, была автоматическая документация API.
Затем я обнаружил, что есть стандарт для документирования API с использованием JSON (или YAML — расширения JSON), под названием Swagger.
И уже существовал веб-интерфейс для Swagger API. Поэтому возможность генерировать документацию Swagger для API позволила бы автоматически использовать этот веб-интерфейс.
В какой-то момент Swagger был передан Linux Foundation и переименован в OpenAPI.
Вот почему, говоря о версии 2.0, обычно говорят «Swagger», а о версии 3+ — «OpenAPI».
Вдохновило FastAPI на
Использовать открытый стандарт для спецификаций API вместо самодельной схемы.
И интегрировать основанные на стандартах инструменты пользовательского интерфейса:
Эти два инструмента выбраны за популярность и стабильность, но даже при беглом поиске можно найти десятки альтернативных интерфейсов для OpenAPI (которые можно использовать с FastAPI).
REST-фреймворки для Flask¶
Существует несколько REST-фреймворков для Flask, но, вложив время и усилия в исследование, я обнаружил, что многие из них прекращены или заброшены, с несколькими нерешёнными Issue (тикет\обращение), из-за которых они непригодны.
Marshmallow¶
Одна из основных возможностей, нужных системам API, — «сериализация» данных, то есть преобразование данных из кода (Python) во что-то, что можно отправить по сети. Например, преобразование объекта с данными из базы в JSON-объект. Преобразование объектов datetime
в строки и т. п.
Ещё одна важная возможность, востребованная API, — валидация данных: убеждаться, что данные валидны с учётом заданных параметров. Например, что какое-то поле — int
, а не произвольная строка. Это особенно полезно для входящих данных.
Без системы валидации данных вам пришлось бы выполнять все проверки вручную в коде.
Именно для этих возможностей и был создан Marshmallow. Это отличная библиотека, я много ей пользовался раньше.
Но она появилась до того, как в Python появились аннотации типов. Поэтому для определения каждой схемы нужно использовать специальные утилиты и классы, предоставляемые Marshmallow.
Вдохновило FastAPI на
Использовать код для автоматического определения «схем», задающих типы данных и их валидацию.
Webargs¶
Ещё одна важная возможность для API — парсинг данных из входящих HTTP-запросов.
Webargs — это инструмент, созданный для этого поверх нескольких фреймворков, включая Flask.
Он использует Marshmallow для валидации данных. И создан теми же разработчиками.
Это отличный инструмент, и я тоже много им пользовался до появления FastAPI.
Информация
Webargs был создан теми же разработчиками, что и Marshmallow.
Вдохновило FastAPI на
Автоматическую валидацию входящих данных HTTP-запроса.
APISpec¶
Marshmallow и Webargs предоставляют валидацию, парсинг и сериализацию как плагины.
Но документации всё ещё не было. Тогда появился APISpec.
Это плагин для многих фреймворков (есть плагин и для Starlette).
Он работает так: вы пишете определение схемы в формате YAML внутри докстринга каждой функции, обрабатывающей маршрут.
И он генерирует схемы OpenAPI.
Так это работает во Flask, Starlette, Responder и т. д.
Но у нас снова возникает проблема: появляется микро-синтаксис внутри строки Python (большой YAML).
Редактор кода мало чем может помочь. И если мы изменим параметры или схемы Marshmallow и забудем также изменить YAML в докстринге, сгенерированная схема устареет.
Информация
APISpec был создан теми же разработчиками, что и Marshmallow.
Вдохновило FastAPI на
Поддержку открытого стандарта для API — OpenAPI.
Flask-apispec¶
Это плагин для Flask, который связывает Webargs, Marshmallow и APISpec.
Он использует информацию из Webargs и Marshmallow, чтобы автоматически генерировать схемы OpenAPI с помощью APISpec.
Отличный и недооценённый инструмент. Он заслуживает большей популярности, чем многие плагины для Flask. Возможно, из-за слишком краткой и абстрактной документации.
Это решило проблему необходимости писать YAML (ещё один синтаксис) в докстрингах Python.
Комбинация Flask, Flask-apispec с Marshmallow и Webargs была моим любимым бэкенд-стеком до создания FastAPI.
Его использование привело к созданию нескольких full-stack генераторов на Flask. Это основные стеки, которые я (и несколько внешних команд) использовали до сих пор:
- https://github.com/tiangolo/full-stack
- https://github.com/tiangolo/full-stack-flask-couchbase
- https://github.com/tiangolo/full-stack-flask-couchdb
И эти же full-stack генераторы стали основой для Генераторов проектов FastAPI.
Информация
Flask-apispec был создан теми же разработчиками, что и Marshmallow.
Вдохновило FastAPI на
Автоматическую генерацию схемы OpenAPI из того же кода, который определяет сериализацию и валидацию.
NestJS (и Angular)¶
Это даже не Python. NestJS — это JavaScript/TypeScript-фреймворк на NodeJS, вдохновлённый Angular.
Он достигает чего-то отчасти похожего на то, что можно сделать с Flask-apispec.
В нём встроена система внедрения зависимостей, вдохновлённая Angular 2. Требуется предварительная регистрация «инжектируемых» компонентов (как и во всех известных мне системах внедрения зависимостей), что добавляет многословности и повторяемости кода.
Поскольку параметры описываются с помощью типов TypeScript (аналог аннотаций типов в Python), поддержка редактора весьма хороша.
Но так как данные о типах TypeScript не сохраняются после компиляции в JavaScript, он не может полагаться на типы для одновременного определения валидации, сериализации и документации. Из‑за этого и некоторых проектных решений для получения валидации, сериализации и автоматической генерации схем приходится добавлять декораторы во многих местах. В итоге это становится довольно многословным.
Он плохо справляется с вложенными моделями. Если JSON-тело запроса — это объект JSON, содержащий внутренние поля, которые сами являются вложенными объектами JSON, это нельзя как следует задокументировать и провалидировать.
Вдохновило FastAPI на
Использовать типы Python для отличной поддержки в редакторе кода.
Иметь мощную систему внедрения зависимостей. Найти способ минимизировать повторение кода.
Sanic¶
Это был один из первых чрезвычайно быстрых Python-фреймворков на основе asyncio
. Он был сделан очень похожим на Flask.
Технические детали
Он использовал uvloop
вместо стандартного цикла asyncio
в Python. Это и сделало его таким быстрым.
Он явно вдохновил Uvicorn и Starlette, которые сейчас быстрее Sanic в открытых бенчмарках.
Вдохновило FastAPI на
Поиск способа достичь сумасшедшей производительности.
Именно поэтому FastAPI основан на Starlette, так как это самый быстрый доступный фреймворк (по данным сторонних бенчмарков).
Falcon¶
Falcon — ещё один высокопроизводительный Python-фреймворк, он минималистичен и служит основой для других фреймворков, таких как Hug.
Он спроектирован так, что функции получают два параметра: «request» и «response». Затем вы «читаете» части из запроса и «пишете» части в ответ. Из‑за такого дизайна невозможно объявить параметры запроса и тело запроса стандартными аннотациями типов Python как параметры функции.
Поэтому валидация данных, сериализация и документация должны выполняться в коде вручную, не автоматически. Либо должны быть реализованы во фреймворке поверх Falcon, как в Hug. Та же особенность есть и в других фреймворках, вдохновлённых дизайном Falcon — с одним объектом запроса и одним объектом ответа в параметрах.
Вдохновило FastAPI на
Поиск способов получить отличную производительность.
Вместе с Hug (так как Hug основан на Falcon) вдохновило FastAPI объявлять параметр response
в функциях.
Хотя в FastAPI это необязательно, и используется в основном для установки HTTP-заголовков, cookie и альтернативных статус-кодов.
Molten¶
Я обнаружил Molten на ранних этапах создания FastAPI. И у него были очень похожие идеи:
- Основан на аннотациях типов Python.
- Валидация и документация из этих типов.
- Система внедрения зависимостей.
Он не использует стороннюю библиотеку для валидации, сериализации и документации, такую как Pydantic, — у него своя. Поэтому такие определения типов данных будет сложнее переиспользовать.
Требуются более многословные конфигурации. И так как он основан на WSGI (вместо ASGI), он не предназначен для использования преимуществ высокой производительности инструментов вроде Uvicorn, Starlette и Sanic.
Система внедрения зависимостей требует предварительной регистрации зависимостей, а зависимости разрешаются по объявленным типам. Поэтому невозможно объявить более одного «компонента», предоставляющего определённый тип.
Маршруты объявляются в одном месте, используя функции, объявленные в других местах (вместо декораторов, которые можно разместить прямо над функцией, обрабатывающей эндпоинт). Это ближе к тому, как это делает Django, чем Flask (и Starlette). Это разделяет в коде вещи, которые довольно тесно связаны.
Вдохновило FastAPI на
Определять дополнительные проверки типов данных, используя значение «по умолчанию» атрибутов модели. Это улучшает поддержку в редакторе кода, и раньше этого не было в Pydantic.
Фактически это вдохновило на обновление частей Pydantic, чтобы поддерживать такой же стиль объявления валидации (вся эта функциональность теперь уже есть в Pydantic).
Hug¶
Hug был одним из первых фреймворков, реализовавших объявление типов параметров API с использованием аннотаций типов Python. Это была отличная идея, которая вдохновила и другие инструменты.
Он использовал собственные типы в объявлениях вместо стандартных типов Python, но это всё равно был огромный шаг вперёд.
Он также был одним из первых фреймворков, генерировавших собственную схему, описывающую весь API в JSON.
Он не был основан на стандартах вроде OpenAPI и JSON Schema. Поэтому интегрировать его с другими инструментами, такими как Swagger UI, было бы непросто. Но, опять же, это была очень инновационная идея.
У него есть интересная и необычная особенность: с помощью одного и того же фреймворка можно создавать и API, и CLI.
Так как он основан на предыдущем стандарте для синхронных веб-фреймворков Python (WSGI), он не может работать с WebSocket и прочим, хотя также демонстрирует высокую производительность.
Информация
Hug был создан Тимоти Кросли, тем же автором isort
, отличного инструмента для автоматической сортировки импортов в файлах Python.
Идеи, вдохновившие FastAPI
Hug вдохновил части APIStar и был одним из наиболее многообещающих инструментов, которые я нашёл, наряду с APIStar.
Hug помог вдохновить FastAPI использовать аннотации типов Python для объявления параметров и автоматически генерировать схему, определяющую API.
Hug вдохновил FastAPI объявлять параметр response
в функциях для установки HTTP-заголовков и cookie.
APIStar (<= 0.5)¶
Прямо перед решением строить FastAPI я нашёл сервер APIStar. В нём было почти всё, что я искал, и отличный дизайн.
Это была одна из первых реализаций фреймворка, использующего аннотации типов Python для объявления параметров и запросов (до NestJS и Molten), которые я видел. Я обнаружил его примерно в то же время, что и Hug. Но APIStar использовал стандарт OpenAPI.
В нём были автоматические валидация данных, сериализация данных и генерация схемы OpenAPI на основе тех же аннотаций типов в нескольких местах.
Определение схемы тела запроса не использовало те же аннотации типов Python, как в Pydantic, — это было ближе к Marshmallow, поэтому поддержка редактора была бы хуже, но всё равно APIStar оставался лучшим доступным вариантом.
На тот момент у него были лучшие показатели в бенчмарках (его превосходил только Starlette).
Сначала у него не было веб‑UI для автоматической документации API, но я знал, что могу добавить к нему Swagger UI.
У него была система внедрения зависимостей. Она требовала предварительной регистрации компонентов, как и другие инструменты, обсуждавшиеся выше. Но всё же это была отличная возможность.
Мне так и не удалось использовать его в полном проекте, поскольку не было интеграции с системой безопасности, поэтому я не мог заменить все возможности, которые имел с full-stack генераторами на основе Flask-apispec. В моём бэклоге было создать пулл-реквест (запрос на изменение), добавляющий эту функциональность.
Затем фокус проекта сместился.
Это перестал быть веб-фреймворк для API, так как автору нужно было сосредоточиться на Starlette.
Сейчас APIStar — это набор инструментов для валидации спецификаций OpenAPI, а не веб-фреймворк.
Информация
APIStar был создан Томом Кристи. Тем самым человеком, который создал:
- Django REST Framework
- Starlette (на котором основан FastAPI)
- Uvicorn (используется Starlette и FastAPI)
Вдохновило FastAPI на
Существование.
Идея объявлять сразу несколько вещей (валидацию данных, сериализацию и документацию) с помощью одних и тех же типов Python, которые одновременно обеспечивают отличную поддержку в редакторе кода, показалась мне блестящей.
После долгих поисков похожего фреймворка и тестирования множества альтернатив APIStar был лучшим доступным вариантом.
Затем APIStar перестал существовать как сервер, а был создан Starlette — новая и лучшая основа для такой системы. Это стало окончательным вдохновением для создания FastAPI.
Я считаю FastAPI «духовным преемником» APIStar, который улучшает и расширяет возможности, систему типов и другие части, опираясь на уроки от всех этих предыдущих инструментов.
Что используется в FastAPI¶
Pydantic¶
Pydantic — это библиотека для определения валидации данных, сериализации и документации (с использованием JSON Schema) на основе аннотаций типов Python.
Благодаря этому он чрезвычайно интуитивен.
Его можно сравнить с Marshmallow. Хотя в бенчмарках он быстрее Marshmallow. И поскольку он основан на тех же аннотациях типов Python, поддержка в редакторе кода отличная.
FastAPI использует его для
Обработки всей валидации данных, сериализации данных и автоматической документации моделей (на основе JSON Schema).
Затем FastAPI берёт эти данные JSON Schema и помещает их в OpenAPI, помимо всех прочих функций.
Starlette¶
Starlette — это лёгкий ASGI фреймворк/набор инструментов, идеально подходящий для создания высокопроизводительных asyncio‑сервисов.
Он очень простой и интуитивный. Спроектирован так, чтобы его было легко расширять, и чтобы компоненты были модульными.
В нём есть:
- Впечатляющая производительность.
- Поддержка WebSocket.
- Фоновые задачи, выполняемые в том же процессе.
- События запуска и завершения.
- Тестовый клиент на базе HTTPX.
- CORS, GZip, статические файлы, потоковые ответы.
- Поддержка сессий и cookie.
- 100% покрытие тестами.
- 100% кодовой базы с аннотациями типов.
- Мало жёстких зависимостей.
В настоящее время Starlette — самый быстрый из протестированных Python-фреймворков. Его превосходит только Uvicorn, который не фреймворк, а сервер.
Starlette предоставляет весь базовый функционал веб-микрофреймворка.
Но он не предоставляет автоматическую валидацию данных, сериализацию или документацию.
Это одна из главных вещей, которые FastAPI добавляет поверх, всё на основе аннотаций типов Python (с использованием Pydantic). Плюс система внедрения зависимостей, утилиты безопасности, генерация схемы OpenAPI и т. д.
Технические детали
ASGI — это новый «стандарт», разрабатываемый участниками core-команды Django. Он всё ещё не является «стандартом Python» (PEP), хотя процесс идёт.
Тем не менее его уже используют как «стандарт» несколько инструментов. Это сильно улучшает совместимость: вы можете заменить Uvicorn на любой другой ASGI-сервер (например, Daphne или Hypercorn) или добавить совместимые с ASGI инструменты, такие как python-socketio
.
FastAPI использует его для
Обработки всех основных веб-частей. Добавляя возможности поверх.
Класс FastAPI
напрямую наследуется от класса Starlette
.
Так что всё, что вы можете сделать со Starlette, вы можете сделать напрямую с FastAPI, по сути это «Starlette на стероидах».
Uvicorn¶
Uvicorn — молниеносный ASGI-сервер, построенный на uvloop и httptools.
Это не веб-фреймворк, а сервер. Например, он не предоставляет инструменты для маршрутизации по путям. Это предоставляет сверху фреймворк, такой как Starlette (или FastAPI).
Это рекомендуемый сервер для Starlette и FastAPI.
FastAPI рекомендует его как
Основной веб-сервер для запуска приложений FastAPI.
Также вы можете использовать опцию командной строки --workers
, чтобы получить асинхронный многопроцессный сервер.
Подробнее см. раздел Развёртывание.
Бенчмарки и скорость¶
Чтобы понять, сравнить и увидеть разницу между Uvicorn, Starlette и FastAPI, см. раздел о Бенчмарках.