[Перевод] Почему стоит начать использовать FastAPI прямо сейчас
Привет, Хабровчане! В преддверии старта занятий в группах базового и продвинутого курсов «Разработчик Python», мы подготовили для вас еще один полезный перевод.
Python всегда был популярен для разработки легковесных веб-приложений благодаря потрясающим фреймворкам, таким как Flask, Django, Falcon и многим другим. Из-за лидирующей позиции Python как языка для машинного обучения, он особенно удобен для упаковки моделей и предоставления их в качестве сервиса.
В течение многих лет Flask был основным инструментом для таких задач, но, если вы еще не слышали, на его место появился новый претендент. FastAPI — это относительно новый фреймворк на Python, создание которого было вдохновлено его предшественниками. Он совершенствует их функционал и исправляет множество недостатков. FastAPI был построен на базе Starlette, и несет в себе кучу потрясающих функций.
В последнее время он приобрел сильную популярность, и после того, как последние 8 месяцев я работал с ним каждый день, с уверенностью могу сказать, что вся шумиха вокруг него вполне оправдана. Если вы еще его не пробовали, то я собрал для вас пять причин, почему вам все-таки стоит с ним познакомиться.
Прекрасный простой интерфейс
Все фреймворки вынуждены балансировать между функциональностью и предоставлением свободы разработчику. Django мощный, но слишком упрямый. С другой стороны, Flask достаточно высокоуровневый, чтобы обеспечить свободу действий, но многое остается за пользователем. FastAPI в этом плане ближе к Flask, но ему удается достичь еще более здорового баланса.
Для примера, давайте посмотрим, как в FastAPI определяется конечная точка.
from fastapi import FastAPI
from pydantic import BaseModel
class User(BaseModel):
email: str
password: str
app = FastAPI()
@app.post("/login")
def login(user: User):
# ...
# do some magic
# ...
return {"msg": "login successful"}
Для определения схемы используется Pydantic, который является не менее потрясающей библиотекой Python для валидации данных. Выглядит достаточно просто, но под капотом происходит много всего интересного. Ответственность за проверку входных данных делегируется FastAPI. Если отправляется неверный запрос, например, в поле электронной почты стоит значение типа int
, вернется соответствующий код ошибки, но приложение не ляжет, выдав Internal Server Error (500). И все это почти бесплатно.
Простой пример приложения с uvicorn
:
uvicorn main:app
Теперь приложение может принимать запросы. В этом случае запрос будет выглядеть следующим образом:
curl -X POST "http://localhost:8000/login" -H "accept: application/json" -H "Content-Type: application/json" -d "{\"email\":\"string\",\"password\":\"string\"}"
Вишенкой на торте будет автоматическая генерация документации в соответствии с OpenAPI с помощью интерактивного интерфейса Swagger.
Интерфейс Swagger для приложения на FastAPI
Async
Одним из самых больших недостатков веб-фреймворков Python WSGI по сравнению с аналогичными в Node.js или Go, была невозможность асинхронной обработки запросов. С момента появления ASGI — это больше не проблема, и FastAPI в полной мере реализует эту возможность. Все, что вам нужно сделать — это просто объявить конечные точки с помощью ключевого слова async следующим образом:
@app.post("/")
async def endpoint():
# ...
# call async functions here with `await`
# ...
return {"msg": "FastAPI is awesome!"}
Внедрение зависимостей
В FastAPI есть действительно классный способ управления зависимостями. Несмотря на то, что разработчиков не заставляют насильно использовать встроенную систему внедрения для обработки зависимостей на конечных точках, такой способ работы настоятельно рекомендуется.
Для примера, давайте создадим конечную точку, где пользователи могут оставлять комментарии к определенным статьям.
from fastapi import FastAPI, Depends
from pydantic import BaseModel
class Comment(BaseModel):
username: str
content: str
app = FastAPI()
database = {
"articles": {
1: {
"title": "Top 3 Reasons to Start Using FastAPI Now",
"comments": []
}
}
}
def get_database():
return database
@app.post("/articles/{article_id}/comments")
def post_comment(article_id: int, comment: Comment, database = Depends(get_database)):
database["articles"][article_id]["comments"].append(comment)
return {"msg": "comment posted!"}
FastAPI автоматически вычислит функцию
get_database в рантайме при вызове конечной точки, поэтому вы сможете использовать возвращаемое значение на свое усмотрение. Для этого есть (по крайней мере) две веские причины.
- Вы можете глобально переопределить зависимости, изменив словарь
app.dependency_overrides
. Так вы сможете облегчить тестирование и мокать объекты. - Зависимость (в нашем случае
get_database
) может выполнять более сложные проверки и позволяет отделить их от бизнес-логики. Дело значительно упрощается. Например, так можно легко реализовать аутентификацию пользователя.
Легкая интеграция с базами данных
Что бы вы ни выбрали, будь то SQL, MongoDB, Redis или что-нибудь другое, FastAPI не заставит вас строить приложение вокруг базы данных. Если вы когда-нибудь работали с MongoDB через Django, вы знаете, насколько это может быть болезненно. С FastAPI вам не нужно будет делать лишний крюк, поскольку добавление базы данных в стек пройдет максимально безболезненно. (Или, если быть точнее, объем работы будет определяться выбранной базой данных, а не сложностями, появившимися из-за использования какого-то конкретного фреймворка.)
Серьезно, посмотрите на эту красоту.
from fastapi import FastAPI, Depends
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
engine = create_engine("sqlite:///./database.db")
Session = sessionmaker(bind=engine)
def get_db():
return Session()
app = FastAPI()
@app.get("/")
def an_endpoint_using_sql(db = Depends(get_db)):
# ...
# do some SQLAlchemy
# ...
return {"msg": "an exceptionally successful operation!"}
Вуаля! Уже вижу, как вы печатаете
pip install fastapi
в терминале на своем компьютере.
Поддержка GraphQL
Когда вы работаете со сложной моделью данных, REST может стать серьезной преградой. Очень не круто, когда малейшее изменение на фронте требует обновления схемы конечной точки. В таких случаях спасает GraphQL. Несмотря на то, что поддержка GraphQL — это не что-то новое для веб-фреймворков Python, Graphene и FastAPI хорошо работают вместе. Нет необходимости дополнительно ставить какие-либо расширения, например graphene_django
для Django, все просто будет работать с самого начала.
+1: Отличная документация
Конечно же, фреймворк не может быть выдающимся, если у него плохая документация. Django, Flask и другие в этом преуспели, и FastAPI от них не отстает. Конечно, поскольку он гораздо моложе, о нем еще нет ни одной книги, но это лишь вопрос времени.
Если вы хотите увидеть FastAPI в действии, то у меня для вас припасено отличное руководство. Я написал подробную инструкцию, с помощью которой вы можете развернуть свою модель машинного обучения на Docker, Docker Compose и GitHub Actions!
Подводя итог, независимо от того ищите ли вы быстрый и легкий фреймворк для работы с вашей моделью глубокого обучения или же что-то более сложное, FastAPI — это ваш вариант. Я почти наверняка уверен, что он вам подойдет.