Ответ
Механизм 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, чтобы потом в любом эндпоинте сказать «а дайте-ка мне мой пул соединений» и не париться. Красота, да и только!