RuntimeError: este bucle de eventos ya se está ejecutando en Python

Creo que estoy recibiendo este error porque mi código llama asyncio.get_event_loop().run_until_complete(foo()) dos veces. Una vez desde foo() y por segunda vez desde la función llamada por foo() . Mi pregunta es entonces: ¿por qué debería ser esto un problema? ¿Por qué debería importarme que este bucle se esté ejecutando?


Se hizo una edición de esta pregunta que, creo, la ocultó (algunas personas prefieren seguir las reglas sin entenderlas, por lo que se eliminó una palabra “ilegal” del título). Desafortunadamente, esto crea confusión.

No me sorprende el hecho de que el error sea elevado. Puedo rastrearlo hasta la fuente de asyncio y ver que los autores de esta biblioteca quisieran hacerlo de esta manera, no hay ningún misterio allí. La parte desconcertante es la razón por la cual los autores de la biblioteca decidieron que es ilegal pedirle al ciclo de eventos que ejecute alguna función hasta que se complete cuando ya se está ejecutando el ciclo.

Podemos reducir el problema a solo dos de estas llamadas y, a través del análisis de casos, veremos que estas son las tres posibilidades:

  1. Ninguna de las dos funciones termina nunca.
  2. Una de las funciones termina eventualmente.
  3. Ambas funciones terminan eventualmente.

Ahora, ¿hay algún comportamiento sano que aborde los tres casos? Para mí, es obvio que hay, o tal vez, son posibles aquí múltiples comportamientos sensatos. Por ejemplo:

  1. Nada especial, la ejecución de ambas funciones está intercalada, y se siguen ejecutando para siempre, tal como se esperaba.
  2. El bucle no devuelve el control al código que sigue a la primera instancia de run_until_complete() hasta que se complete la segunda función (por lo tanto, no se ejecutará ningún código después de run_until_complete() .
  3. Una vez que termina la última función, el bucle devuelve el control al primer objeto de código que invocó run_until_complete ignorando todos los demás sitios de invocación.

Ahora, puedo entender que este comportamiento puede no ser algo que todos querrían. Pero, dado que esta biblioteca decidió otorgar a los progtwigdores el control sobre el inicio / detención del bucle de eventos, también debería enfrentar las consecuencias de tales decisiones. Hacer un error al iniciar el mismo bucle varias veces impide que el código de la biblioteca haga esto, lo que reduce la calidad y la utilidad de las bibliotecas que utilizan asyncio (que es el caso, por ejemplo, de aiohttp ).

Event loop running: es un punto de entrada de su progtwig asíncrono. Gestiona la ejecución de todas las rutinas, tareas, callbacks. Ejecutar el bucle mientras se está ejecutando no tiene sentido: en cierto modo es como tratar de ejecutar un ejecutor de trabajos desde el mismo ejecutor de trabajos que ya se está ejecutando.

Ya que tiene esta pregunta, creo que puede malinterpretar cómo funciona asyncio. Por favor, lea este artículo , no es grande y ofrece una buena introducción.

Actualizaciones:

No hay absolutamente ningún problema en agregar varias cosas para ser ejecutadas por un bucle de eventos mientras este bucle ya se está ejecutando. Puedes hacerlo simplemente esperándolo:

 await coro() # add coro() to be run by event loop blocking flow here until coro() is finished 

o creando una tarea:

 asyncio.ensure_future(coro()) # add coro() to be run by event loop without blocking flow here 

Como puede ver, no necesita los métodos de bucle de evento de llamada para hacer que algo se ejecute por él.

El método del bucle de eventos, como run_forever o run_until_complete , son solo una forma de iniciar el bucle de eventos en general.

run_until_complete(foo()) significa: “agregue foo() para que se ejecute en el bucle de eventos y ejecute el propio bucle de eventos hasta que no se foo() “.