← Назад к вопросам

Делал ли асинхронный контекстный менеджер на проекте

1.0 Junior🔥 101 комментариев
#Python Core#Асинхронность и многопоточность

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Да, неоднократно

Асинхронные контекстные менеджеры — это мощный инструмент для управления ресурсами в асинхронном коде. Я использовал их во множестве реальных проектов.

Практический пример: асинхронное подключение к БД

Один из самых частых кейсов — управление асинхронным подключением к базе данных:

from contextlib import asynccontextmanager
from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession
from sqlalchemy.orm import sessionmaker

class DatabaseManager:
    def __init__(self, database_url: str):
        self.engine = create_async_engine(
            database_url,
            echo=False,
            pool_size=10,
            max_overflow=20
        )
        self.async_session = sessionmaker(
            self.engine,
            class_=AsyncSession,
            expire_on_commit=False
        )

    @asynccontextmanager
    async def get_session(self):
        async with self.async_session() as session:
            try:
                yield session
                await session.commit()
            except Exception:
                await session.rollback()
                raise
            finally:
                await session.close()

Так я использовал его в проекте:

db_manager = DatabaseManager("postgresql+asyncpg://user:pass@localhost/db")

async def get_user(user_id: int):
    async with db_manager.get_session() as session:
        user = await session.get(User, user_id)
        return user

Пример: управление HTTP сессией

Второй кейс — управление aiohttp сессией с гарантированным закрытием:

from contextlib import asynccontextmanager
import aiohttp

class HTTPClient:
    @asynccontextmanager
    async def session(self):
        session = aiohttp.ClientSession()
        try:
            yield session
        finally:
            await session.close()

client = HTTPClient()

async def fetch_data(url: str):
    async with client.session() as session:
        async with session.get(url) as response:
            return await response.json()

Пример: лок для асинхронных операций

Использовал асинхронные контекстные менеджеры для управления распределенными локами:

from contextlib import asynccontextmanager
import asyncio

class AsyncLock:
    def __init__(self, key: str, timeout: int = 30):
        self.key = key
        self.timeout = timeout
        self.lock = asyncio.Lock()

    @asynccontextmanager
    async def __aenter__(self):
        async with self.lock:
            yield

    async def __aexit__(self, exc_type, exc_val, exc_tb):
        pass

async def register_user(email: str):
    async with lock:
        await check_email_exists(email)
        await create_user(email)

Пример: измерение времени выполнения

Асинхронный контекстный менеджер для логирования и мониторинга:

from contextlib import asynccontextmanager
import time
import logging

logger = logging.getLogger(__name__)

@asynccontextmanager
async def measure_time(operation_name: str):
    start = time.time()
    try:
        yield
    finally:
        duration = time.time() - start
        logger.info(f"{operation_name} completed in {duration:.2f}s")

async def process_data():
    async with measure_time("data_processing"):
        await heavy_computation()

Ключевые моменты

  • @asynccontextmanager — декоратор для создания асинхронного контекстного менеджера
  • async with — синтаксис для использования
  • Гарантированное очищение ресурсов — блок finally срабатывает даже при исключениях
  • Использование в production — применял во множестве микросервисов и data pipeline'ов

Асинхронные контекстные менеджеры — стандартный инструмент в моем наборе для надежного управления ресурсами в асинхронном коде.