python

Почему Вы должны попробовать FastAPI?

  • среда, 4 декабря 2019 г. в 00:23:41
https://habr.com/ru/post/478620/
  • Python
  • API


image Лого взято из Github репозитория FastAPI


FastAPI — относительно новый веб-фреймворк, написанный на языке программирования Python для создания REST (а если сильно постараться то и GraphQL) API, основанный на новых возможностях Python 3.6+, таких как: подсказки типов (type-hints), нативная асинхронность (asyncio). Помимо всего прочего, FastAPI плотно интегрируется с OpenAPI-schema и автоматически генерирует документацию для вашего API посредством Swagger и ReDoc


FastAPI построен на базе Starlette и Pydantic.
StarletteASGI микро-фреймворк для написания веб-приложений.
Pydantic — библиотека для парсинга и валидации данных основанная на Python type-hints.


Что говорят о FastAPI?


"[...] Я использую FastAPI очень часто в последние дни. [...] Я однозначно планирую использовать его для всех ML сервисов моей команды в Microsoft. Некоторые из них интегрируются в Windows и некоторые продукты Office."
Kabir Khan — Microsoft (ref)


"Если вы хотите выучить ещё один фреймворк для написания REST API, взгляните на FastAPI [...] Он быстрый, прост в использовании и изучении. [...]"


"Теперь мы используем FastAPI для наших API [...] Я думаю он вам понравится! [...]"
Ines Montani — Matthew Honnibal — Explosion AI founders — spaCy creators (ref) — (ref)


Минимальное API созданное с помощью FastAPI


Я постараюсь показать Вам как создать простое, но в то же время полезное API с документацией для разработчиков. Мы будем писать генератор случайных фраз!


Установка необходимых компонентов


pip install uvicorn fastapi pydantic

Новый модуль!
Uvicorn — это ASGI-совместимый веб-сервер, который мы будем использовать для запуска нашего приложения.


Для начала создадим основу нашего приложения.


from fastapi import FastAPI

app = FastAPI(title="Random phrase")

Это приложение уже работает и его можно запустить.
Пропишите данную команду в вашем терминале и откройте страничку в браузере по адресу http://127.0.0.1:8000/docs.


uvicorn <имя_вашего_файла>:app

Но пока в нашем приложении не обозначено ни одного эндпоинта — давайте это исправим!


База данных


Так как мы пишем генератор случайных фраз, мы очевидно должны их где-то хранить. Для этого я выбрал простой python-dict.


Создадим файл db.py и начнём писать код.


Импортируем необходимые модули:


import typing
import random
from pydantic import BaseModel
from pydantic import Field

После — обозначим две модели: входная фраза (та, которую нам будет отправлять пользователь) и "выходная" (та, которую мы будем отправлять пользователю).


class PhraseInput(BaseModel):
    """Phrase model"""

    author: str = "Anonymous"  # имя автора. Если не передано - используется стандартное значение.
    text: str = Field(..., title="Text", description="Text of phrase", max_length=200)  # Текст фразы. Максимальное значение - 200 символов.

class PhraseOutput(PhraseInput):
    id: typing.Optional[int] = None  # ID фразы в нашей базе данных.

После этого, создадим простой класс для работы с БД:



class Database:
    """
    Our **fake** database.
    """

    def __init__(self):
        self._items: typing.Dict[int, PhraseOutput] = {}  # id: model

    def get_random(self) -> int:
        # Получение случайной фразы
        return random.choice(self._items.keys())

    def get(self, id: int) -> typing.Optional[PhraseOutput]:
        # Получение фразы по ID
        return self._items.get(id)

    def add(self, phrase: PhraseInput) -> PhraseOutput:
        # Добавление фразы

        id = len(self._items) + 1
        phrase_out = PhraseOutput(id=id, **phrase.dict())
        self._items[phrase_out.id] = phrase_out
        return phrase_out

    def delete(self, id: int) -> typing.Union[typing.NoReturn, None]:
        # Удаление фразы

        if id in self._items:
            del self._items[id]
        else:
            raise ValueError("Phrase doesn't exist")

Теперь можно приступить к написанию самого API.


API


Создадим файл main.py и импортируем следующие модули:


from fastapi import FastAPI
from fastapi import HTTPException
from db import PhraseInput
from db import PhraseOutput
from db import Database

Инициализируем наше приложение и базу данных:


app = FastAPI(title="Random phrase")
db = Database()

И напишем простой метод получения случайной фразы!


@app.get(
    "/get",
    response_description="Random phrase",
    description="Get random phrase from database",
    response_model=PhraseOutput,
)
async def get():
    try:
        phrase = db.get(db.get_random())
    except IndexError:
        raise HTTPException(404, "Phrase list is empty")
    return phrase

Как Вы можете заметить, в декораторе я также указываю некоторые другие значения, нужные для генерации более красивой документации :) В официальной документации Вы можете посмотреть на все возможные параметры.


В этом куске кода, мы пытаемся получить случайную фразу из базы данных, а если база данных пуста — возвращаем ошибку с кодом 404.


Аналогично пишем другие методы:


@app.post(
    "/add",
    response_description="Added phrase with *id* parameter",
    response_model=PhraseOutput,
)
async def add(phrase: PhraseInput):
    phrase_out = db.add(phrase)
    return phrase_out

@app.delete("/delete", response_description="Result of deleting")
async def delete(id: int):
    try:
        db.delete(id)
    except ValueError as e:
        raise HTTPException(404, str(e))

И всё! Наше маленькое, но полезное API — готово!


Теперь мы можем запустить приложение с помощью uvicorn, открыть интерактивную документацию (http://127.0.0.1/docs) и попробовать наше API!



Полезные материалы


Конечно, я не смог рассказать Вам о всех возможностях FastAPI, например таких как: умная DI система, middlewares, куки, стандартные методы аутентификация в API (jwt, oauth2, api-key) и многое другое!


Но целью этой статьи является не столько обзор всех возможностей этого фреймворка, а сколько толчок Вас изучить его самим. FastAPI имеет замечательную документацию с кучей примеров.


Код из статьи на Github
Официальная документация
Репозиторий на Github