tutorial loop espaƱol asyncio async python python-asyncio

python - loop - Asyncio.gather vs asyncio.wait



python async api (3)

asyncio.gather y asyncio.wait parecen tener usos similares: tengo un montón de cosas asíncronas que quiero ejecutar / esperar (no necesariamente esperando que una termine antes de que comience la siguiente). Usan una sintaxis diferente y difieren en algunos detalles, pero me parece muy poco pitónico tener 2 funciones que tienen una superposición tan grande en la funcionalidad. ¿Qué me estoy perdiendo?


Aunque similar en casos generales ("ejecutar y obtener resultados para muchas tareas"), cada función tiene alguna funcionalidad específica para otros casos:

asyncio.gather

Devuelve una instancia futura, lo que permite la agrupación de tareas de alto nivel:

import asyncio from pprint import pprint import random async def coro(tag): print(">", tag) await asyncio.sleep(random.uniform(1, 3)) print("<", tag) return tag loop = asyncio.get_event_loop() group1 = asyncio.gather(*[coro("group 1.{}".format(i)) for i in range(1, 6)]) group2 = asyncio.gather(*[coro("group 2.{}".format(i)) for i in range(1, 4)]) group3 = asyncio.gather(*[coro("group 3.{}".format(i)) for i in range(1, 10)]) all_groups = asyncio.gather(group1, group2, group3) results = loop.run_until_complete(all_groups) loop.close() pprint(results)

Todas las tareas en un grupo pueden cancelarse llamando a group2.cancel() o incluso all_groups.cancel() . Ver también .gather(..., return_exceptions=True) ,

asyncio.wait

Admite la espera para detenerse después de que se realiza la primera tarea, o después de un tiempo de espera especificado, lo que permite una precisión de operaciones de menor nivel:

import asyncio import random async def coro(tag): print(">", tag) await asyncio.sleep(random.uniform(0.5, 5)) print("<", tag) return tag loop = asyncio.get_event_loop() tasks = [coro(i) for i in range(1, 11)] print("Get first result:") finished, unfinished = loop.run_until_complete( asyncio.wait(tasks, return_when=asyncio.FIRST_COMPLETED)) for task in finished: print(task.result()) print("unfinished:", len(unfinished)) print("Get more results in 2 seconds:") finished2, unfinished2 = loop.run_until_complete( asyncio.wait(unfinished, timeout=2)) for task in finished2: print(task.result()) print("unfinished2:", len(unfinished2)) print("Get all other results:") finished3, unfinished3 = loop.run_until_complete(asyncio.wait(unfinished2)) for task in finished3: print(task.result()) loop.close()


También noté que puede proporcionar un grupo de corutinas en wait () simplemente especificando la lista:

result=loop.run_until_complete(asyncio.wait([ say(''first hello'', 2), say(''second hello'', 1), say(''third hello'', 4) ]))

Mientras que la agrupación en recolectar () se realiza simplemente especificando múltiples corutinas:

result=loop.run_until_complete(asyncio.gather( say(''first hello'', 2), say(''second hello'', 1), say(''third hello'', 4) ))


asyncio.wait tiene un nivel más bajo que asyncio.gather .

Como su nombre lo indica, asyncio.gather se centra principalmente en recopilar los resultados. espera un montón de futuros y devuelve sus resultados en un orden dado.

asyncio.wait solo espera en el futuro. y en lugar de darle los resultados directamente, le da tareas pendientes y pendientes. tienes que recolectar manualmente los valores.

Además, puede especificar esperar a que finalicen todos los futuros o solo el primero con wait .