tutorial run loop has español attribute asyncio async python python-3.4 python-asyncio

run - process async python



Al usar asyncio, ¿cómo permite que finalicen todas las tareas en ejecución antes de apagar el bucle de eventos? (2)

Tengo el siguiente código:

@asyncio.coroutine def do_something_periodically(): while True: asyncio.async(my_expensive_operation()) yield from asyncio.sleep(my_interval) if shutdown_flag_is_set: print("Shutting down") break

Ejecuto esta función hasta que esté completo. El problema ocurre cuando se establece el apagado: la función se completa y las tareas pendientes nunca se ejecutan. (Usted ve esto como un error

task: <Task pending coro=<report() running at script.py:33> wait_for=<Future pending cb=[Task._wakeup()]>>

) ¿Cómo programo un cierre correctamente?

Para dar algún contexto, estoy escribiendo un monitor del sistema que lee de / proc / stat cada 5 segundos, calcula el uso de la CPU en ese período y luego envía el resultado a un servidor. Deseo seguir programando estos trabajos de supervisión hasta que reciba sigterm, cuando dejo de programar, espero a que terminen todos los trabajos actuales y salgo con elegancia.


A partir de Python 3.7, la respuesta anterior usa varias API en desuso (asyncio.async y Task.all_tasks, @ asyncio.coroutine, yield from, etc.) y debería usar esto:

import asyncio my_interval = 1 shutdown_flag_is_set = False async def my_expensive_operation(): print(await asyncio.sleep(10, result="Expensive operation finished.")) async def do_something_periodically(*, loop): global shutdown_flag_is_set while True: loop.create_task(my_expensive_operation()) await asyncio.sleep(my_interval) if shutdown_flag_is_set: print("Shutting down") break await asyncio.gather(*asyncio.all_tasks(loop)) loop = asyncio.get_event_loop() try: loop.run_until_complete(do_something_periodically(loop=loop)) except KeyboardInterrupt: shutdown_flag_is_set = True


Puede recuperar tareas sin terminar y ejecutar el ciclo de nuevo hasta que finalicen, luego cierre el ciclo o salga de su programa.

pending = asyncio.Task.all_tasks() loop.run_until_complete(asyncio.gather(*pending))

  • pendiente es una lista de tareas pendientes.
  • asyncio.gather () permite esperar en varias tareas a la vez.

Si quiere asegurarse de que todas las tareas se completen dentro de una corutina (tal vez tenga una corutina "principal"), puede hacerlo de esta manera, por ejemplo:

@asyncio.coroutine def do_something_periodically(): while True: asyncio.async(my_expensive_operation()) yield from asyncio.sleep(my_interval) if shutdown_flag_is_set: print("Shutting down") break yield from asyncio.gather(*asyncio.Task.all_tasks())

Además, en este caso, dado que todas las tareas se crean en la misma coroutine, ya tiene acceso a las tareas:

@asyncio.coroutine def do_something_periodically(): tasks = [] while True: tasks.append(asyncio.async(my_expensive_operation())) yield from asyncio.sleep(my_interval) if shutdown_flag_is_set: print("Shutting down") break yield from asyncio.gather(*tasks)