Creo que estoy recibiendo este error, ya que mi código de llamadas asyncio.get_event_loop().run_until_complete(foo()) dos veces. Una vez de foo() y el segundo tiempo de la función de llamada por foo(). Mi pregunta es entonces: ¿por qué debería ser esto un problema? ¿Por qué debería siquiera se preocupan de que este bucle se ejecuta?


Hubo una edición hecha a esta pregunta que, creo, oscurecido (algunas personas prefieren seguir las reglas sin la comprensión de ellos, por lo tanto un «ilegal» palabra fue retirado del título). Por desgracia, esto crea confusión.

No estoy sorprendido por el hecho de que se produce el error. Puedo rastrear de nuevo a la asyncio fuente y ver que los autores de esta biblioteca quería hacerlo de esta manera, no hay ningún misterio. La desconcertante es la razón por la que los autores de la biblioteca decidido que es ilegal hacer de bucle de eventos para ejecutar alguna función para la finalización cuando el bucle está ya en marcha.

Podemos reducir el problema a sólo dos de esas llamadas, y a través de análisis de casos, vamos a ver que estas son las tres posibilidades:

  1. Ninguna de las dos funciones que nunca termina.
  2. Una de las funciones con el tiempo termina.
  3. Ambas funciones con el tiempo terminar.

Ahora, ¿hay algún cuerdo comportamiento frente a los tres casos? Para mí, es obvio que no existe, o, tal vez, son múltiples cuerdo de los comportamientos que son posibles aquí. Por ejemplo:

  1. Nada especial, la ejecución de ambas funciones se intercalan y se mantenga funcionando para siempre, como era de esperar.
  2. El bucle no devolver el control al código que sigue a la primera instancia de run_until_complete() hasta la segunda función completa (por lo tanto no hay código después de run_until_complete() será ejecutado.
  3. Después de la última función termina, el bucle se devuelve el control a la primera de código objeto que invoca run_until_complete ignorando todos los otros invocación sitios.

Ahora, puedo entender que este comportamiento no puede ser algo que todos queremos. Pero, desde esta biblioteca decidió dar a los programadores de control sobre iniciar /detener el bucle de eventos, también debe conocer las consecuencias de tales decisiones. Lo que es un error empezar el mismo bucle varias veces se opone a la biblioteca de código de nunca hacer esto, lo que reduce la calidad y la utilidad de las bibliotecas de la utilización de asyncio (que es de hecho el caso, por ejemplo, aiohttp).

InformationsquelleAutor wvxvw | 2017-10-19

3 Comentarios

  1. 15

    Bucle de eventos en ejecución – es un punto de entrada de su async programa. Gestiona el funcionamiento de todas las corrutinas, tareas, devoluciones de llamada. Bucle de ejecución mientras se ejecuta no tiene sentido: en algún tipo es como tratar de ejecutar el trabajo ejecutor de los mismos, ya trabajo en ejecución el ejecutor.

    Ya que se tiene esta pregunta, supongo que se puede malinterpretar una manera de cómo asyncio obras. Por favor, lea este artículo – no es muy grande y da una buena introducción.

    Upd:

    No hay absolutamente ningún problema en añadir varias cosas para ser ejecutado por evento bucle while este bucle ya se está ejecutando. Usted puede hacerlo sólo a la espera de que:

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

    o la creación de la tarea:

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

    Como usted puede ver, usted no necesita un evento de llamada del bucle métodos para hacer algo que se corrió por ella.

    Bucle de eventos del método, tales como run_forever o run_until_complete — son solo un formas el evento de inicio del bucle en general.

    run_until_complete(foo()) significa: «agregar foo() sea ejecutado por el bucle de eventos y ejecutar el bucle de eventos de sí mismo hasta foo() no está hecho».

    • …pero no estoy ejecutando el bucle de eventos, estoy corriendo foo() ¿por qué no me llegan a ejecutar el bucle de forma explícita? Que en la Tierra gustaría que que? Es como mover las manos de su reloj de pared con sus manos… para hacer que el tiempo se mueva hacia adelante…
    • Re’ artículo – gracias. Voy a leer ahora. En comparación con cualquier idioma que poner la concurrencia en su diseño desde el principio, asyncio es tan malo, en muchos niveles… que parece que más allá de la redención. Todo lo que es malo, el diseño, la implementación, la documentación de Python… en general fue un decente idioma, pero además… yo no sé ni cómo describirlo.
    • Bueno, el artículo es muy superficial, con un par hello-world nivel de ejemplos que no retiene el agua, cuando se aplica a algo más realista… :/
    • Realmente creo que contiene todas las cosas necesarias para ver cómo utilizar asyncio. Si quieres algo más profundo, para entender cómo asyncio sí funciona, que puedo asesoramiento a ver este video: youtube.com/watch?v=MCs5OvhV9S4 Es más complejo, pero se muestra cómo el bucle de eventos (abstracción) organizado y cómo se las arregla las cosas.
    • Yo no sé ni por dónde empezar a describir todos los problemas que en este artículo se pasa por alto. Creo que la persona que la escribió, simplemente, nunca había una necesidad de cualquier tipo de simultaneidad y acabo de escribir es como un «teórico» del ejercicio. De todos modos, nada de lo dispuesto en este artículo o en su respuesta explica por qué es un problema al intentar ejecutar algo en el mismo bucle mientras que algo más se está ejecutando. Usted piensa que no tiene sentido, porque se limita a muy poco realista caso cuando sólo tienes un programa muy simple, con un solo punto de entrada y no de las bibliotecas. Ningún programa útil es así.
    • He actualizado respuesta, espero que te ayudarán.
    • Bueno, realmente hay un problema, que es por diseño de asyncio… El problema es que el programador nunca debe iniciar / detener la ejecución del bucle. Esto sólo es intrínsecamente mala idea. Ahora, desde el bucle debe ser iniciado, hay un problema: ¿quién empieza? Pueden biblioteca código de empezar? Debe ser iniciado a partir de la no-código asincrónico, quizás varias veces. Lo que si ni el lugar sabe nada acerca de los otros y sólo quiere iniciar el bucle? Para responder a esto, es necesario explicar por qué asyncio lanza cuando dos funciones diferentes intente iniciarlo. Sólo constatar el hecho de que no es útil
    • asyncio.ensure_future(coro()) fue la solución para mí 👍
    • en algunos contextos, como un decator en simple unittest.Testcase métodos, funciona bien. Pero las otras respuestas anteriores dicen que sólo funcionará correctamente en el nivel superior. Si usted está en otro contexto, incluyendo como descubrí que se ejecuta en un 3.6+ listo ipython que ya se ha construido en async la manipulación, se sopla con las preguntas de error. Tal vez no me gusta, pero veo por qué sería así.

  2. 4

    Tengo el problema se resuelve mediante el uso de la nest_async

    pip install nest_asyncio

    y añadiendo a continuación las líneas en el archivo.

    import nest_asyncio
    nest_asyncio.apply()
  3. 2

    Estoy escribiendo esto de no ser condescendiente, pero a explicar cómo podemos manejar la situación en la que simplemente el sistema de colas async funciones y a la espera de sus resultados de forma sincrónica, mientras que el bucle de eventos se está ejecutando, no funciona.

    run_until_complete no es para la ejecución de cualquier número arbitrario de async funciones de forma sincrónica, es para ejecutar el principal punto de entrada de toda su async programa. Esta restricción no es inmediatamente evidente a partir de la documentación.

    Desde las bibliotecas como aiohttp va a la cola de su propio punto de entrada para ejecutarse como un servidor y bloquear el bucle síncrono de operaciones mediante run_until_complete o run_forever, el bucle de eventos estará ejecutando, y usted no será capaz de ejecutar independiente operaciones síncronas en ese bucle de eventos y esperar el resultado dentro de ese hilo.

    Que se dice, si usted tiene a la cola de una operación asíncrona en un ejecutando el bucle de eventos desde dentro de un contexto de sincronización y obtener el resultado como una función regular, que puede no ser posible. Su mejor apuesta es pasar de un sincrónica de devolución de llamada para ser llamado una vez que el async operación finalice. Que por supuesto va a ralentizar el bucle de eventos.

    Otra manera de manejar la situación es ejecutar dentro de su código de inicio y de limpieza de las devoluciones de llamada de la async http biblioteca que está utilizando. He aquí un la muestra de cómo se puede lograr esto.

Dejar respuesta

Please enter your comment!
Please enter your name here