Asyncio.gather vs asyncio.wait

asyncio.gather et asyncio.wait semblent avoir des utilisations similaires: j’ai un tas de choses asynchrones que je veux exécuter / attendre (ne pas attendre nécessairement la fin avant la prochaine). Ils utilisent une syntaxe différente, et diffèrent dans certains détails, mais il me semble très absurde d’avoir 2 fonctions qui ont un tel chevauchement de fonctionnalités. Qu’est-ce que je rate?

Bien que similaires dans les cas généraux (“exécuter et obtenir des résultats pour de nombreuses tâches”), chaque fonction possède des fonctionnalités spécifiques pour d’autres cas:

asyncio.gather()

Retourne une instance Future, permettant un regroupement de tâches de haut niveau:

 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) 

Toutes les tâches d'un groupe peuvent être annulées en appelant group2.cancel() ou même all_groups.cancel() . Voir aussi .gather(..., return_exceptions=True) ,

asyncio.wait()

Prend en charge l’attente de l’arrêt après la première tâche ou après un délai spécifié, permettant ainsi une précision des opérations de niveau inférieur:

 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() 

asyncio.wait est plus bas que asyncio.gather .

Comme son nom l’indique, asyncio.gather se concentre principalement sur la collecte des résultats. il attend beaucoup de contrats à terme et retourne ses résultats dans un ordre donné.

asyncio.wait attend simplement sur les futures. et au lieu de vous donner directement les résultats, cela donne des tâches accomplies et en attente. vous devez collecter manuellement les valeurs.

De plus, vous pouvez spécifier d’attendre que tous les contrats à terme se terminent ou le premier avec wait .

J’ai également remarqué que vous pouvez fournir un groupe de coroutines en attente () en spécifiant simplement la liste:

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

Considérant que le regroupement dans rassembler () se fait en spécifiant simplement plusieurs coroutines:

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