Usa asyncio para tareas paralelas.

Me preguntaba cómo podría usar asyncio para manejar tareas similares a las que hace nodeJS. Quiero ejecutar tareas al mismo tiempo sin abrir hilos. Ejemplo:

import asyncio @asyncio.coroutine def my_coroutine(task_name, seconds_to_sleep=3): print('{0} sleeping for: {1} seconds'.format(task_name, seconds_to_sleep)) yield from asyncio.sleep(seconds_to_sleep) print('{0} is finished'.format(task_name)) loop = asyncio.get_event_loop() tasks = [ my_coroutine('task1', 4), my_coroutine('task2', 3), my_coroutine('task3', 2)] loop.run_until_complete(asyncio.wait(tasks)) loop.close() 

saldrá:

 task1 sleeping for: 4 seconds task2 sleeping for: 3 seconds task3 sleeping for: 2 seconds task3 is finished task2 is finished task1 is finished 

pero cuando trato de hacerlo con una tarea diferente, no funcionará así.

 import asyncio import timeit @asyncio.coroutine def my_coroutine(task_name): print('order placed for ' + task_name) print(timeit.timeit('1 + 3 ', number=50000000)) print(task_name + ' done') loop = asyncio.get_event_loop() tasks = [ my_coroutine('task1'), my_coroutine('task2'), my_coroutine('task3')] loop.run_until_complete(asyncio.wait(tasks)) loop.close() 

salidas

 order placed for task2 0.6677237730912453 task2 done order placed for task1 0.6627442526498016 task1 done order placed for task3 0.665618849882418 task3 done 

asyncio no ejecuta las cosas en paralelo. Ejecuta una tarea hasta que espera, luego pasa a la siguiente. El sleep en su primer ejemplo es lo que hace que las tareas se controlen entre sí. El segundo ejemplo no espera nada, por lo que cada tarea se ejecuta hasta que se completa antes de que el bucle de eventos pueda dar el control a otra tarea.

Si agrega algo que se puede esperar (p. Ej., asyncio.sleep ) en su coroutine, cada uno le dará control y le dará a los otros la oportunidad de correr.

 @asyncio.coroutine def my_coroutine(task_name): print('order placed for ' + task_name) yield from asyncio.sleep(0) # Another coroutine will resume here. print(timeit.timeit('1 + 3 ', number=50000000)) yield from asyncio.sleep(0) # Another coroutine will resume here. print(task_name + ' done')