В чем разница между синхронным и асинхронным контекстным менеджером в Python?

Ответ

Ключевое различие в том, что асинхронные контекстные менеджеры позволяют выполнять await-операции (например, сетевые запросы, работу с БД) внутри методов входа и выхода, что невозможно в синхронных.

Сравнение

Характеристика Синхронный менеджер Асинхронный менеджер
Оператор with async with
Метод входа __enter__() async def __aenter__()
Метод выхода __exit__() async def __aexit__()
Назначение Управление ресурсами (файлы, блокировки) в синхронном коде. Управление ресурсами, требующими асинхронных операций для инициализации или завершения.

Практический пример

Представим подключение к базе данных, которое является асинхронной операцией.

Синхронный менеджер (не подходит для асинхронных операций):

class SyncFileManager:
    def __init__(self, filename):
        self.filename = filename

    def __enter__(self):
        print("Открытие файла...")
        self.file = open(self.filename, 'w')
        return self.file

    def __exit__(self, exc_type, exc_val, exc_tb):
        print("Закрытие файла...")
        self.file.close()

with SyncFileManager('test.txt') as f:
    f.write('hello')

Асинхронный менеджер (идеален для I/O-bound задач):

import asyncio

class AsyncDatabaseConnection:
    async def __aenter__(self):
        print("Подключение к БД...")
        await asyncio.sleep(0.1) # Имитация асинхронного подключения
        print("Подключение установлено.")
        return self

    async def __aexit__(self, exc_type, exc_val, exc_tb):
        print("Закрытие соединения...")
        await asyncio.sleep(0.1) # Имитация асинхронного закрытия
        print("Соединение закрыто.")

async def main():
    async with AsyncDatabaseConnection() as conn:
        print("Выполнение запроса...")

asyncio.run(main())

Таким образом, асинхронные менеджеры необходимы для корректного управления ресурсами в среде asyncio, где операции по их получению и освобождению сами являются неблокирующими.