Estoy tratando de hacer un montón de solicitudes (~ 1000) usando Asyncio y la biblioteca aiohttp, pero tengo un problema en el que no puedo encontrar mucha información.
Cuando ejecuto este código con 10 urls, funciona bien. Cuando lo ejecuto con más de 100 urls, se rompe y me da RuntimeError: Event loop is closed
error RuntimeError: Event loop is closed
.
import asyncio import aiohttp @asyncio.coroutine def get_status(url): code = '000' try: res = yield from asyncio.wait_for(aiohttp.request('GET', url), 4) code = res.status res.close() except Exception as e: print(e) print(code) if __name__ == "__main__": urls = ['https://google.com/'] * 100 coros = [asyncio.Task(get_status(url)) for url in urls] loop = asyncio.get_event_loop() loop.run_until_complete(asyncio.wait(coros)) loop.close()
La traza de stack se puede encontrar aquí .
Cualquier ayuda o idea sería muy apreciada, ya que me he estado golpeando la cabeza por esto durante algunas horas. Obviamente, esto sugeriría que se ha cerrado un bucle de eventos que aún debería estar abierto, pero no veo cómo es posible.
Tienes razón, loop.getaddrinfo usa un ThreadPoolExecutor
para ejecutar socket.getaddrinfo
en un hilo.
Estás usando asyncio.wait_for con un tiempo de espera, lo que significa que res = yield from asyncio.wait_for...
generará un asyncio.TimeoutError
después de 4 segundos. Luego, get_status
coroutines devuelve None
y el bucle se detiene. Si un trabajo finaliza después de eso, intentará progtwigr una callback en el bucle de eventos y genera una excepción ya que ya está cerrado.
El error se archiva como https://github.com/python/asyncio/issues/258 Manténgase sintonizado.
Como solución rápida, sugiero usar un ejecutor personalizado, por ejemplo,
loop = asyncio.get_event_loop() executor = concurrent.futures.ThreadPoolExecutor(5) loop.set_default_executor(executor)
Antes de terminar su progtwig por favor haga
executor.shutdown(wait=True) loop.close()