Вы не можете использовать with
внутри функции, и контекстный менеджер остается открытым, нет. Блок with with aiohttp.ClientSession() as session:
выходит, как только вы используете return
для выхода из сопрограммы __aenter__
!
Для конкретного случая ввод aiohttp.ClientSession()
диспетчера контекста ничего не делает, кроме как возвращает self
. Так что для этого типа достаточно просто создать экземпляр и сохранить его в self.session
и ожидать self.session.close()
, да.
Общий общий шаблон для вложенного асинхронного диспетчера контекста заключается в ожидании методов __aenter__
и __aexit__
вложенного асинхронного диспетчера контекста от ваших собственных таких методов (и, возможно, передачи информации об исключении) :
class MySession:
def __init__(self):
self.session = None
async def __aenter__(self):
self.session = aiohttp.ClientSession()
await self.session.__aenter__()
return self
async def __aexit__(self, exc_type, exc_val, exc_tb):
if self.session:
return await self.session.__aexit__(exc_type, exc_val, exc_tb)
Технически говоря, вы должны сначала убедиться в наличии фактического атрибута __aexit__
перед тем, как войти во вложенный менеджер контекста:
class MySession:
def __init__(self):
self.session = None
self._session_aexit = None
async def __aenter__(self):
self.session = aiohttp.ClientSession()
self._session_aexit = type(self.session).__aexit__
await self.session.__aenter__()
return self
async def __aexit__(self, exc_type, exc_val, exc_tb):
if self.session:
return await self._session_aexit.__aexit__(
self.session, exc_type, exc_val, exc_tb)
См. официальный PEP, который добавил концепцию .