FastAPI Python

Содержание
Введение
Установка
Запуск сервиса
Простейший пример
Проверка типа
Swagger docs
Похожие статьи

Введение

FastAPI — веб-фреймворк для создания API, написанный на Python. Один из самых быстрых и популярных (после Django и Flask) веб-фреймворков, написанных на Python (на 2023 год).

FastAPI активно использует декораторы, аннотации типов и интроспекцию кода, что позволяет уменьшить количество шаблонного кода в веб-приложении. FastAPI автоматически генерирует и отображает документацию согласно спецификации OpenAPI.

В основе FastAPI лежат две библиотеки — Starlette (ASGI-фреймворк) и Pydantic (для описания схем данных); FastAPI склеивает их и реализует некоторые дополнительные возможности — регистрацию представлений через внедрение зависимостей, работу с аутентификацией и авторизацией, автоматическую генерацию документации и другое.

Возможно использование как асинхронных, так и синхронных представлений.

Самый любимый (most loved) python-веб-фреймворк по опросу среди разработчиков на портале Stack Overflow (2021, 2022).

Официальный сайт - https://fastapi.tiangolo.com/

Некоторые изображения будет лучше видно если открывать их в отдельной вкладке.

Установка

python -m venv venv
source venv/Scripts/activate
touch requirements.txt
vi requirements.txt

fastapi==0.110.1 uvicorn==0.29.0

python -m pip install --upgrade pip
python -m pip install -r requirements.txt

Collecting fastapi Downloading fastapi-0.110.0-py3-none-any.whl (92 kB) |████████████████████████████████| 92 kB 5.7 MB/s Collecting uvicorn[standard] Downloading uvicorn-0.27.1-py3-none-any.whl (60 kB) |████████████████████████████████| 60 kB 4.1 MB/s Collecting typing-extensions>= 4.8.0 Downloading typing_extensions-4.10.0-py3-none-any.whl (33 kB) Collecting starlette<0.37.0,>= 0.36.3 Downloading starlette-0.36.3-py3-none-any.whl (71 kB) |████████████████████████████████| 71 kB 4.5 MB/s Collecting pydantic&33;= 1.8,&33;= 1.8.1,&33;= 2.0.0,&33;= 2.0.1,&33;= 2.1.0,<3.0.0,>= 1.7.4 Downloading pydantic-2.6.2-py3-none-any.whl (394 kB) |████████████████████████████████| 394 kB 6.4 MB/s Collecting pydantic-core= = 2.16.3 Downloading pydantic_core-2.16.3-cp38-none-win_amd64.whl (1.9 MB) |████████████████████████████████| 1.9 MB ... Collecting annotated-types>= 0.4.0 Downloading annotated_types-0.6.0-py3-none-any.whl (12 kB) Collecting anyio<5,>= 3.4.0 Downloading anyio-4.3.0-py3-none-any.whl (85 kB) |████████████████████████████████| 85 kB ... Collecting idna>= 2.8 Downloading idna-3.6-py3-none-any.whl (61 kB) |████████████████████████████████| 61 kB 4.5 MB/s Collecting exceptiongroup>= 1.0.2 Downloading exceptiongroup-1.2.0-py3-none-any.whl (16 kB) Collecting sniffio>= 1.1 Downloading sniffio-1.3.1-py3-none-any.whl (10 kB) Collecting h11>= 0.8 Downloading h11-0.14.0-py3-none-any.whl (58 kB) |████████████████████████████████| 58 kB 3.8 MB/s Collecting click>= 7.0 Using cached click-8.1.7-py3-none-any.whl (97 kB) Collecting websockets>= 10.4 Downloading websockets-12.0-cp38-cp38-win_amd64.whl (124 kB) |████████████████████████████████| 124 kB 6.8 MB/s Collecting httptools>= 0.5.0 Downloading httptools-0.6.1-cp38-cp38-win_amd64.whl (60 kB) |████████████████████████████████| 60 kB ... Collecting colorama>= 0.4 Downloading colorama-0.4.6-py2.py3-none-any.whl (25 kB) Collecting python-dotenv>= 0.13 Downloading python_dotenv-1.0.1-py3-none-any.whl (19 kB) Collecting pyyaml>= 5.1 Downloading PyYAML-6.0.1-cp38-cp38-win_amd64.whl (157 kB) |████████████████████████████████| 157 kB ... Collecting watchfiles>= 0.13 Downloading watchfiles-0.21.0-cp38-none-win_amd64.whl (279 kB) |████████████████████████████████| 279 kB 6.8 MB/s Installing collected packages: typing-extensions, sniffio, idna, exceptiongroup, colorama, pydantic-core, h11, click, anyio, annotated-types, websockets, watchfiles, uvicorn, starlette, pyyaml, python-dotenv, pydantic, httptools, fastapi Successfully installed annotated-types-0.6.0 anyio-4.3.0 click-8.1.7 colorama-0.4.6 exceptiongroup-1.2.0 fastapi-0.110.0 h11-0.14.0 httptools-0.6.1 idna-3.6 pydantic-2.6.2 pydantic-core-2.16.3 python-dotenv-1.0.1 pyyaml-6.0.1 sn sniffio-1.3.1 starlette-0.36.3 typing-extensions-4.10.0 uvicorn-0.27.1 watchfiles-0.21.0 websockets-12.0

Запуск сервиса

Если файл с кодом называется main.py а приложение вызывается как app, сервис будет запускаться командой uvicorn main:app

# main.pyapp = FastAPI()

uvicorn main:app

FastAPI запущенный таким образом остановится если вы закроете терминал. Если вы подлкючаетесь к облачному серверу uvicorn остановится после оключения.

Чтобы FastAPI постоянно работал на моём облачном сервере Beget я устанавливаю gunicorn и затем выполняю команду

gunicorn main:app --workers 4 --worker-class uvicorn.workers.UvicornWorker --bind 0.0.0.0:80

Простейший пример

touch main.py
vi main.py

from fastapi import FastAPI app = FastAPI() @app.get("/") async def root(): return {"message": "Hello World"}

uvicorn main:app

INFO: Started server process [33972] INFO: Waiting for application startup. INFO: Application startup complete. INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)

main - так как наш скрипт main.py

app - так как app = FastAPI()

uvicorn main:app --port 8003 --reload

INFO: Will watch for changes in these directories: ['C:\Users\Andrei\sandbox\python\fastapi'] INFO: Uvicorn running on http://127.0.0.1:8003 (Press CTRL+C to quit) INFO: Started reloader process [32404] using WatchFiles INFO: Started server process [19652] INFO: Waiting for application startup. INFO: Application startup complete.

FastAPI Hello World изображение с сайта www.devhops.ru
FastAPI
Hello World

Благодаря --reload внесённые изменения подгрузятся автоматически

from fastapi import FastAPI app = FastAPI() @app.get("/", description="This is our first route.") async def root(): return {"message": "Hello World"} @app.post("/") async def post(): return {"message": "hello from the post route"} @app.put("/") async def put(): return {"message": "hello from the put route"}

Если в браузере открыть

localhost:8003/docs

Появится автоматически созданная документация Swagger

FastAPI Swagger изображение с сайта www.devhops.ru
FastAPI
Swagger

РЕКЛАМА от Google. Может быть недоступна в вашем регионе.

Конец рекламы от Google. Если в блоке пусто считайте это рекламой моей телеги

Если обратится по несуществующему адресу FastAPI вернёт сообщение

detail "Not Found"

FastAPI detail not found изображение с сайта www.devhops.ru
FastAPI
detail Not Found
FastAPI item_id изображение с сайта www.devhops.ru
FastAPI
item id

Проверка типа

В предыдущем примере мы не использовали type hints при объявлении get_item(item_id)

@app.get("/items/{item_id}") async def get_item(item_id): return {"item_id": item_id}

FastAPI без type hints изображение с сайта www.devhops.ru
FastAPI
Любой тип

Если теперь с помощью type hint указать тип как int, обратиться к строке уже не получится

@app.get("/items/{item_id}") async def get_item(item_id: int): return {"item_id": item_id}

FastAPI int изображение с сайта www.devhops.ru
FastAPI
Только int

int по-прежнему работает

FastAPI без type hints изображение с сайта www.devhops.ru
FastAPI
Только int

Swagger docs

Как уже было показано выше обратившись к /docs можно изучить Swagger документацию к нашему API

Протестируем её на примере item_id

Прямо из документации можно отправить curl запрос с желаемым id. 0 как целое число приведёт к успеху

FastAPI без type hints изображение с сайта www.devhops.ru
FastAPI
Только int

Обратите внимание на Response body

{ "item_id": 0 }

Здесь 0 это число. Если бы type hint был не int а str, 0 всё-равно можно бы было передать, просто вернулся бы он как строка

{ "item_id": "0" }

"test" как строка приведёт к ошибке.

FastAPI без type hints изображение с сайта www.devhops.ru
FastAPI
Только int

FastAPI перебирает адреса сверху вниз. Если вам нужно, чтобы у какого-то адрес был приоритет, ставьте его выше.

Например, если я хочу выделить специальный item с именем default нельзя объявить метод снизу.

@app.get("/items/{item_id}") async def get_item(item_id: str): return {"item_id": item_id} @app.get("/items/default") async def get_default_item(): return {"message": "This is default item"}

В этом случае все мой обращения к

http://localhost:8003/items/default

Будут возвращать

item_id "default"

Так как до последнего адреса FastAPI просто не дойдет - предыдущий полностью подходит под запрос.

Если теперь поменять функции местами, default будет выполняться раньше чем всё остальное, но на все остальные запросы это никак не повлияет.

@app.get("/items/default") async def get_default_item(): return {"message": "This is default item"} @app.get("/items/{item_id}") async def get_item(item_id: str): return {"item_id": item_id}

http://localhost:8003/items/default

message "This is default item"

http://localhost:8003/items/regulat

item_id "regular"

INFO: 127.0.0.1:65380 - "GET /favicon.ico HTTP/1.1" 404 Not Found

Похожие статьи
FastAPI
list comprehension: Абстракция списка
Python
Pydantic
Пример API с БД
Циклы
Фреймворки

РЕКЛАМА хостинга Beget, которым я пользуюсь более десяти лет

Изображение баннера

Конец рекламы хостинга Beget, который я всем рекомендую.

Поиск по сайту

Подпишитесь на Telegram канал @aofeed чтобы следить за выходом новых статей и обновлением старых

Перейти на канал

@aofeed

Задать вопрос в Телеграм-группе

@aofeedchat

Контакты и сотрудничество:
Рекомендую наш хостинг beget.ru
Пишите на info@urn.su если Вы:
1. Хотите написать статью для нашего сайта или перевести статью на свой родной язык.
2. Хотите разместить на сайте рекламу, подходящую по тематике.
3. Реклама на моём сайте имеет максимальный уровень цензуры. Если Вы увидели рекламный блок недопустимый для просмотра детьми школьного возраста, вызывающий шок или вводящий в заблуждение - пожалуйста свяжитесь с нами по электронной почте
4. Нашли на сайте ошибку, неточности, баг и т.д. ... .......
5. Статьи можно расшарить в соцсетях, нажав на иконку сети: