9.1 Контекстные менеджеры
Вы помните, как мы использовали оператор with, чтобы контролировать доступ к ресурсу? С его помощью можно было точно отследить, когда ресурс начал использоваться, и когда этот процесс закончился. То же самое можно делать и для «асинхронных ресурсов».
Асинхронные контекстные менеджеры (AsyncContextManager) используются для управления ресурсами в асинхронном программировании, обеспечивая правильное открытие и закрытие ресурсов в асинхронных функциях. Они работают аналогично обычным контекстным менеджерам, но предназначены для использования в асинхронных функциях с ключевыми словами async with.
Я не буду подробно про это рассказывать, так как в ближайшее время вы точно не будете создавать свои асинхронные контекстные менеджеры, а к тому времени, когда решите это делать, всё равно всё забудете. Но познакомить с самой концепцией я вас хочу.
Создание асинхронного контекстного менеджера
Асинхронные контекстные менеджеры определяются с использованием методов __aenter__ и __aexit__. Эти методы аналогичны методам __enter__ и __exit__ в обычных контекстных менеджерах, но являются асинхронными.
-
__aenter__(): Асинхронный метод, вызываемый при входе в контекст. -
__aexit__(exc_type, exc, tb): Асинхронный метод, вызываемый при выходе из контекста. Принимает три аргумента: тип исключения, само исключение и трассировку(traceback).
Пример создания асинхронного контекстного менеджера
import asyncio
class AsyncContextManager:
async def __aenter__(self):
print("Enter context")
return self
async def __aexit__(self, exc_type, exc, tb):
print("Exit context")
async def main():
async with AsyncContextManager():
print("Inside context")
asyncio.run(main())
Вот как будет выполняться этот код:
- Асинхронно запустится функция
main(). - Функция
main()начнёт выполняться. - Создастся объект типа
AsyncContextManager. - У объекта
AsyncContextManagerвызовется метод__aenter__(). - Выведется
print("Enter context"). - Выполнится код
print("Inside context"). - У объекта
AsyncContextManagerвызовется метод__aexit__(). - Завершится выполнение функции
main().
9.2 Примеры использования
В примере выше не обязательно использовать именно асинхронную версию менеджера контекста — код будет работать, даже если его сделать синхронным.
Но асинхронный менеджер нужен, если внутри блока with вызывается асинхронная функция или используется оператор await.
Асинхронный контекстный менеджер для работы с файлами
В этом примере используется библиотека aiofiles для асинхронного чтения и записи файлов. Асинхронный контекстный менеджер aiofiles.open позволяет безопасно открывать и закрывать файлы в асинхронном контексте.
import aiofiles
import asyncio
async def main():
async with aiofiles.open('example.txt', mode='w') as file:
await file.write('Hello, world!')
asyncio.run(main())
Асинхронный контекстный менеджер для сетевых операций
В этом примере используется библиотека aiohttp для выполнения асинхронных HTTP-запросов. Асинхронные контекстные менеджеры ClientSession и session.get обеспечивают правильное управление соединениями.
import aiohttp
import asyncio
async def fetch(url):
async with aiohttp.ClientSession() as session:
async with session.get(url) as response:
return await response.text()
async def main():
html = await fetch('https://example.com')
print(html)
asyncio.run(main())
Асинхронные контекстные менеджеры обеспечивают автоматическое управление ресурсами, такими как файлы, сетевые соединения и другие ресурсы, которые необходимо открывать и закрывать.
Методы __aenter__ и __aexit__ позволяют выполнять асинхронные операции при входе и выходе из контекста, обеспечивая параллельное выполнение задач. Использование асинхронных контекстных менеджеров помогает избежать утечек ресурсов и гарантирует, что все ресурсы будут корректно освобождены.
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ