while terminar for español ejemplos como ciclo bucle python python-3.x asynchronous coroutine python-asyncio

python - terminar - ¿Cómo crear un bucle de eventos con coroutines rodantes ejecutándose para siempre?



for i in range python español (4)

¿Realmente intentaste ejecutar los tres ejemplos que diste? La diferencia en el comportamiento es bastante obvia.

Como nunca dijiste lo que esperas, no se dice qué es correcto y qué no lo es. Las tres implementaciones pueden ser correctas o incorrectas. Puedo decirle qué comportamiento tiene cada implementación y por qué tiene tal comportamiento; Sólo tú sabes si es correcto.

En el segundo ejemplo ( yield from asyncio.sleep(1) ), las dos corrutinas se ejecutan simultáneamente. Esto significa que cada uno ejecutará por su cuenta; hello_world imprime Hello World cada segundo y good_evening imprime Good Evening cada segundo.

Los otros dos ejemplos usan time.sleep(1) , que está bloqueando. Esto significa que cuando la primera función (cualquiera que sea; digamos que es hello_world ) llega a time.sleep(1) , el programa completo se bloqueará durante un segundo . Esto significa que cuando hello_world duerme, good_evening tampoco puede ejecutarse, y viceversa.

El programa se ejecuta así:

  1. Se introduce el bucle.
  2. El bucle llama a hello_world .
  3. time.sleep(1) en hello_world . El programa duerme un segundo.
  4. Hello World impreso.
  5. hello_world cede.
  6. El bucle llama good_evening .
  7. Good Evening impresas.
  8. time.sleep(1) en good_evening . El programa duerme un segundo.
  9. good_evening rendimientos.
  10. Ir a 2.

Por lo tanto, tanto Hello World como Good Evening aparecen cada dos segundos, porque hay dos time.sleep(1) entre cada print . Notarías fácilmente que si ejecutas los dos ejemplos.

Para evitar el cambio de contexto, quiero crear un gran bucle para atender tanto las conexiones de red como algunas rutinas.

Aquí está la implementación para las funciones normales:

import asyncio import time def hello_world(loop): print(''Hello World'') loop.call_later(1, hello_world, loop) def good_evening(loop): print(''Good Evening'') loop.call_later(1, good_evening, loop) print(''step: asyncio.get_event_loop()'') loop = asyncio.get_event_loop() print(''step: loop.call_soon(hello_world, loop)'') loop.call_soon(hello_world, loop) print(''step: loop.call_soon(good_evening, loop)'') loop.call_soon(good_evening, loop) try: # Blocking call interrupted by loop.stop() print(''step: loop.run_forever()'') loop.run_forever() except KeyboardInterrupt: pass finally: print(''step: loop.close()'') loop.close()

Aquí está la implementación para coroutines:

import asyncio @asyncio.coroutine def hello_world(): while True: yield from asyncio.sleep(1) print(''Hello World'') @asyncio.coroutine def good_evening(): while True: yield from asyncio.sleep(1) print(''Good Evening'') print(''step: asyncio.get_event_loop()'') loop = asyncio.get_event_loop() try: print(''step: loop.run_until_complete()'') loop.run_until_complete(asyncio.wait([ hello_world(), good_evening() ])) except KeyboardInterrupt: pass finally: print(''step: loop.close()'') loop.close()

Y el mixto:

import asyncio import time def hello_world(loop): print(''Hello World'') loop.call_later(1, hello_world, loop) def good_evening(loop): print(''Good Evening'') loop.call_later(1, good_evening, loop) @asyncio.coroutine def hello_world_coroutine(): while True: yield from asyncio.sleep(1) print(''Hello World Coroutine'') @asyncio.coroutine def good_evening_coroutine(): while True: yield from asyncio.sleep(1) print(''Good Evening Coroutine'') print(''step: asyncio.get_event_loop()'') loop = asyncio.get_event_loop() print(''step: loop.call_soon(hello_world, loop)'') loop.call_soon(hello_world, loop) print(''step: loop.call_soon(good_evening, loop)'') loop.call_soon(good_evening, loop) print(''step: asyncio.async(hello_world_coroutine)'') asyncio.async(hello_world_coroutine()) print(''step: asyncio.async(good_evening_coroutine)'') asyncio.async(good_evening_coroutine()) try: loop.run_forever() except KeyboardInterrupt: pass finally: print(''step: loop.close()'') loop.close()

Como puedes ver, cada función de coroutine tiene un bucle while rodeado. ¿Cómo puedo hacerlo como el normal? Es decir, cuando está listo, se llama después del tiempo de retardo dado, pero no solo pone un bucle allí.


Si realmente desea eliminar el bucle while de las coroutinas (no estoy seguro de por qué cree que es necesario; es la forma más natural de hacer lo que está tratando de hacer), puede usar asyncio.async (o asyncio.ensure_future on Python 3.4.4+) para programar la rutina para que se ejecute de nuevo en la siguiente iteración del bucle de eventos:

import asyncio @asyncio.coroutine def hello_world(): yield from asyncio.sleep(1) print(''Hello World'') asyncio.async(hello_world()) @asyncio.coroutine def good_evening(): yield from asyncio.sleep(1) print(''Good Evening'') asyncio.async(good_evening()) print(''step: asyncio.get_event_loop()'') loop = asyncio.get_event_loop() try: print(''step: loop.run_until_complete()'') asyncio.async(hello_world()) asyncio.async(good_evening()) loop.run_forever() except KeyboardInterrupt: pass finally: print(''step: loop.close()'') loop.close()

Tenga en cuenta que debe volver a usar loop.run_forever() si hace esto, ya que hello_world / good_evening se good_evening inmediatamente después de imprimir ahora.


# asyncio_coroutine_forever.py import asyncio async def hello_world(): await asyncio.sleep(1) print(''Hello World'') await good_evening() async def good_evening(): await asyncio.sleep(1) print(''Good Evening'') await hello_world() loop = asyncio.get_event_loop() try: loop.run_until_complete(hello_world()) loop.run_until_complete(good_evening()) loop.run_forever() finally: print(''closing event loop'') loop.close()


import asyncio @asyncio.coroutine def hello_world_coroutine(): yield from asyncio.sleep(1) print(''Hello World Coroutine'') yield from hello_world_coroutine() @asyncio.coroutine def good_evening_coroutine(): yield from asyncio.sleep(1) print(''Good Evening Coroutine'') yield from good_evening_coroutine() print(''step: asyncio.get_event_loop()'') loop = asyncio.get_event_loop() try: print(''step: loop.run_until_complete()'') loop.run_until_complete(asyncio.wait([ hello_world_coroutine(), good_evening_coroutine() ])) except KeyboardInterrupt: pass finally: print(''step: loop.close()'') loop.close()

UPD

Este código alcanzaría la máxima profundidad de recursión. Podría ser porque Python no tiene optimización de llamadas de cola. Deje el código aquí como un ejemplo incorrecto.