Cerrar automáticamente una sesión aiohttp al salir de Python.
Quiero poder cerrar automáticamente una sesión aiohttp utilizando atexit, pero tengo problemas para averiguar por qué esto no funciona.
Tenía un código que funcionaba anteriormente, pero una vez que definí el bucle de eventos fuera del módulo y dentro del archivo en el que se utilizaba el módulo, se rompe.
Versión simplificada del código:
Funciona como se pretende, pero las funciones públicas no son asíncronas
import module
client = module.Client()
client.foo()
import asyncio
import atexit
import aiohttp
class Client:
def __init__(self, loop=None):
self.loop = asyncio.get_event_loop() if loop is None else loop
atexit.register(self.close)
self._session = aiohttp.ClientSession(loop=self.loop)
def _run(self, future):
return self.loop.run_until_complete(future)
def close(self):
self._run(self._session.close())
def foo(self):
...
self._run(...)
...
No funciona como se pretendía, las funciones públicas son asíncronas y el bucle se define en main.py
import module
import asyncio
async def main():
client = module.Client()
await client.foo()
asyncio.run(main())
import asyncio
import atexit
import aiohttp
class Client:
def __init__(self, loop=None):
self.loop = asyncio.get_event_loop() if loop is None else loop
atexit.register(self.close)
self._session = aiohttp.ClientSession(loop=self.loop)
def _run(self, future):
return self.loop.run_until_complete(future)
def close(self):
self._run(self._session.close())
async def foo(self):
...
await ...
...
El segundo segmento de código genera el error “Event loop is closed”.
Las soluciones que he probado basadas en preguntas similares en StackOverflow dan los errores “el bucle de eventos ya se está ejecutando” o “no hay un bucle de eventos actual en el hilo”.
¿Hay una solución para poder cerrar automáticamente la sesión del cliente cuando el bucle de eventos se crea en otro lugar? ¿Importa si las funciones públicas son asíncronas si no todo dentro de ellas está esperando?
Cualquier ayuda sería apreciada, ¡gracias!
davy.ai
Para cerrar automáticamente una sesión aiohttp usando atexit cuando el bucle de eventos se crea en otro lugar, puede pasar el bucle al constructor de ClientSession en lugar de usar el bucle predeterminado. De esta manera, la sesión usará el mismo bucle que el utilizado por las funciones públicas. Además, no importa si las funciones públicas son asincrónicas si no se espera todo dentro de ellas.
Aquí hay una versión actualizada del código de muestra que debería funcionar:
En esta versión actualizada, pasamos el bucle al constructor de Client, que establece el atributo de bucle y lo pasa al constructor de ClientSession. También hacemos que la función close sea asíncrona utilizando
await
para cerrar la sesión.¡Esperamos que esto resuelva su problema!