Гайды

Быстрый старт с FastAPI

venv и uvicorn, первое приложение и OpenAPI, структура каталогов, POST с Pydantic, lifespan и частые ошибки.

~11 мин чтения

Быстрый старт с FastAPI

FastAPI — ASGI-фреймворк на Python с автоматической OpenAPI-документацией, валидацией через Pydantic и нативной поддержкой async. Этот гайд — минимальный рабочий каркас проекта; дальше — маршрутизация и Dependency Injection и Pydantic: валидация моделей.


1. Окружение

bash
python -m venv .venv
.venv\Scripts\activate   # Windows
pip install "fastapi[standard]" uvicorn

Рекомендуемая связка: Python 3.11+, FastAPI 0.115+ (проверяйте документацию под вашу версию).


2. Первое приложение

main.py:

python
from fastapi import FastAPI

app = FastAPI(title="Demo API", version="0.1.0")


@app.get("/health")
def health():
    return {"status": "ok"}


@app.get("/items/{item_id}")
def read_item(item_id: int, q: str | None = None):
    return {"item_id": item_id, "q": q}

Запуск для разработки:

bash
uvicorn main:app --reload --host 0.0.0.0 --port 8000
  • Документация Swagger: http://localhost:8000/docs
  • ReDoc: http://localhost:8000/redoc
  • Сырой OpenAPI JSON: /openapi.json

3. Структура каталогов (рекомендация на рост)

text
app/
  __init__.py
  main.py          # создание FastAPI(), подключение роутеров
  api/
    routes/
      items.py     # APIRouter(prefix="/items", tags=["items"])
  core/
    config.py      # настройки из env (pydantic-settings)

В main.py:

python
from fastapi import FastAPI
from app.api.routes import items

app = FastAPI()
app.include_router(items.router, prefix="/api")

4. POST и тело запроса

python
from pydantic import BaseModel, Field

class ItemCreate(BaseModel):
    name: str = Field(min_length=1, max_length=200)
    price: float = Field(gt=0)

@app.post("/items", status_code=201)
def create_item(payload: ItemCreate):
    return {"id": 1, **payload.model_dump()}

Pydantic автоматически валидирует JSON и отдаёт 422 при ошибках. Подробнее — Pydantic в API.


5. Коды ответа и исключения

python
from fastapi import HTTPException

@app.get("/items/{item_id}")
def get_item(item_id: int):
    if item_id < 1:
        raise HTTPException(status_code=404, detail="Item not found")
    return {"id": item_id}

Или Response / декоратор @app.get(..., responses={404: {...}}) для OpenAPI.


6. Lifespan (замена on_event)

python
from contextlib import asynccontextmanager
from fastapi import FastAPI

@asynccontextmanager
async def lifespan(app: FastAPI):
    # старт: пулы БД, клиенты
    yield
    # остановка: закрыть соединения

app = FastAPI(lifespan=lifespan)

Сюда же помещают инициализацию пула asyncpg — см. гайд asyncpg + FastAPI, раздел FastAPI про async и БД и документацию asyncpg.


7. Прод: процессы и прокси

В Linux чаще запускают gunicorn с воркером uvicorn.workers.UvicornWorker и несколькими процессами за Nginx или systemd — см. Docker и Nginx. У uvicorn включайте --proxy-headers и список доверенных IP (--forwarded-allow-ips), чтобы X-Forwarded-* корректно восстанавливали схему и клиентский адрес за балансировщиком.

Для health-check в оркестраторе достаточно лёгкого GET /health без обращения к БД; «глубокая» проверка — отдельным путём, чтобы не убивать пул соединений на каждый kubelet probe.


8. Частые ошибки

ОшибкаКак избежать
Блокирующий код в async defВынести в run_in_executor или использовать sync-роуты/воркеры
Забыли --reload только в devВ проде — несколько worker'ов uvicorn/gunicorn
Секреты в кодеpydantic-settings + .env вне Git
Забыли закрыть ресурсы при исключенииyield в lifespan и в Depends, не «ручной» teardown в random местах

Дальше


Дальше: тег FastAPI · тег Python