Для чего используется механизм lifespan в FastAPI и как он работает

Ответ

Механизм lifespan в FastAPI — это современный способ управления ресурсами, которые должны быть инициализированы перед запуском приложения и очищены после его остановки. Он заменяет устаревшие обработчики событий startup и shutdown.

Основная задача — выполнение асинхронного кода для подготовки и освобождения ресурсов, таких как подключения к базам данных, кэшу или запуск фоновых задач.

Работает lifespan через асинхронный контекстный менеджер, который передается в конструктор FastAPI. Код до yield выполняется при старте, а код после yield — при остановке.

Пример реализации:

from contextlib import asynccontextmanager
from fastapi import FastAPI

# Условная функция для подключения к БД
async def connect_to_db():
    print("Подключение к базе данных...")
    # Здесь логика подключения
    return {"connection": "active"}

# Условная функция для закрытия соединения
async def close_db_connection():
    print("Соединение с базой данных закрыто.")

@asynccontextmanager
async def lifespan(app: FastAPI):
    # --- Код, выполняемый при старте приложения ---
    db_connection = await connect_to_db()
    app.state.db = db_connection # Сохраняем состояние для доступа в эндпоинтах
    print("Приложение запущено.")

    yield # В этот момент приложение начинает принимать запросы

    # --- Код, выполняемый при остановке приложения ---
    await close_db_connection()
    print("Приложение остановлено.")

app = FastAPI(lifespan=lifespan)

@app.get("/")
async def root():
    # Доступ к состоянию, созданному в lifespan
    return {"db_status": app.state.db}

Ключевые преимущества:

  • Современный подход: Является рекомендуемой заменой для @app.on_event("startup") и @app.on_event("shutdown").
  • Асинхронность: Полностью поддерживает async/await.
  • Управление состоянием: Позволяет безопасно передавать инициализированные ресурсы (например, пул соединений) в приложение через app.state или yield.

Ответ 18+ 🔞

Смотри, вот тебе жизненный цикл, или как его там — lifespan в FastAPI. Это, блядь, такая штука, чтобы твоё приложение не стартовало как попало, а с подготовкой, как нормальный человек, который перед выходом из дома проверяет, выключил ли он утюг и взял ли ключи.

Раньше-то были эти startup и shutdown события, ну, знаешь, старый дедовский способ. А теперь — вот он, красавец, lifespan. Суть проще пареной репы: всё, что до yield, выполняется, когда приложение просыпается и потягивается. А всё, что после — когда оно ложится спать и ему надо выключить свет, закрыть холодильник и отключить все свои движухи.

Вот смотри, как это выглядит в коде, чтобы не быть голословным:

from contextlib import asynccontextmanager
from fastapi import FastAPI

# Допустим, нам надо к базе подключиться
async def connect_to_db():
    print("Цепляемся к базе данных...")
    # Тут всякая магия с драйверами
    return {"connection": "active"}

# А это — чтобы красиво отцепиться, а не бросить всё и сбежать
async def close_db_connection():
    print("Всё, база, прощай, соединение рвём.")

@asynccontextmanager
async def lifespan(app: FastAPI):
    # --- ЭТО ВЫПОЛНЯЕТСЯ ПРИ СТАРТЕ ---
    # Подключаемся
    db_connection = await connect_to_db()
    app.state.db = db_connection # Кидаем подключение в app.state, чтобы потом в эндпоинтах им пользоваться
    print("Приложение встало с кровати и готово к труду.")

    yield # А вот тут, внимание, — пауза! Приложение начинает работать и принимать запросы

    # --- ЭТО ВЫПОЛНЯЕТСЯ ПРИ ВЫКЛЮЧЕНИИ ---
    # Всё, пора на боковую, закрываем за собой
    await close_db_connection()
    print("Приложение легло спать. Всем спокойной ночи.")

app = FastAPI(lifespan=lifespan)

@app.get("/")
async def root():
    # А вот и наше сохранённое состояние, живое и здоровое
    return {"db_status": app.state.db}

И в чём же, спрашивается, вся соль, ёпта? А соль в том, что это теперь каноничный, модный и молодёжный способ. Полностью асинхронный, без всяких костылей. И главное — состояние можно передавать аккуратно, через app.state или прямо через yield, чтобы потом в любом эндпоинте сказать «а дайте-ка мне мой пул соединений» и не париться. Красота, да и только!