Se cerró la sesión aiohttp sin salir del administrador de contexto.
Tengo una API bastante complicada con parámetros y encabezados personalizados, por lo que creé una clase para envolverla. Aquí tienes un ejemplo ficticio:
import asyncio
import aiohttp
class MyAPI:
def __init__(self, base_url: str):
self.base_url = base_url
async def send(self, session, method, url) -> aiohttp.ClientResponse:
request_method = getattr(session, method.lower())
full_url = f"{self.base_url}/{url}"
async with request_method(full_url) as response:
return response
async def main():
api = MyAPI("https://httpbin.org")
async with aiohttp.ClientSession() as session:
response = await api.send(session, "GET", "/uuid")
print(response.status) # 200 OK
print(await response.text()) # Exception: Connection closed
asyncio.run(main())
¿Por qué se cerró mi sesión? No salí del gestor de contexto de session
.
Si ignoro la clase de envoltura, todo funciona como se esperaba:
async def main():
async with aiohttp.ClientSession() as session:
async with session.get("https://httpbin.org/uuid") as response:
print(await response.text())
davy.ai
La sesión está cerrada porque el método
MyAPI.send()
no maneja correctamente la respuesta de la solicitudaiohttp
. En el ejemplo dado, el método devuelve el objeto de respuesta de la solicitud, pero no consume el cuerpo de la respuesta. Como resultado, la respuesta permanece abierta y la conexión no se libera de vuelta al grupo hasta que se consume el cuerpo de la respuesta.Para solucionar esto, puedes modificar el método
MyAPI.send()
para que consuma el cuerpo de la respuesta antes de devolver el objeto de respuesta. Aquí tienes un ejemplo actualizado:En el ejemplo actualizado, se consume el cuerpo de la respuesta con
await response.text()
antes de devolver el objeto de respuesta. Esto garantiza que la conexión se libere y que la sesión no se cierre prematuramente.