276 votes

Asyncio.gather vs asyncio.wait

asyncio.gather et asyncio.wait semblent avoir les mêmes usages: j'ai un tas de async choses que je veux exécuter/attendre (pas nécessairement s'attendre à terminer avant la prochaine on commence). Ils utilisent une syntaxe différente, et ne diffèrent que par quelques détails, mais il semble très à l'onu-pythonic pour moi d'avoir 2 fonctions qui ont un énorme chevauchement de fonctionnalité. Ce qui me manque?

323voto

Udi Points 6298

Bien que similaire dans le cas général ("exécuter et obtenir des résultats pour de nombreuses tâches"), chaque fonction dispose de quelques fonctionnalités spécifiques pour les autres cas:

asyncio.gather()

Renvoie un Futur instance, permettant de haut niveau de regroupement des tâches:

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 dans un groupe peut être annulé par l'appelant group2.cancel() ou même all_groups.cancel(). Voir aussi .gather(..., return_exceptions=True),

asyncio.wait()

Prend en charge en attente d'être arrêté après la première tâche est effectuée, ou après un certain délai d'attente, permettant d'abaisser le niveau de précision des opérations:

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

75voto

ospider Points 1507

asyncio.wait est plus faible niveau que asyncio.gather.

Comme son nom l'indique, asyncio.gather se concentre principalement sur la collecte de résultats. il attend sur un tas de contrats à terme et la restitution de leurs résultats dans un ordre donné.

asyncio.wait attend simplement sur les contrats à terme. et au lieu de vous donner les résultats directement, il donne de fait et les tâches en attente. vous devez mannually recueillir les valeurs.

En outre, vous pouvez choisir d'attendre pour tous les contrats à terme de finition, ou seulement le premier avec wait.

22voto

Johny Ebanat Points 61

J'ai aussi remarqué que vous pouvez fournir un groupe de coroutines à wait () 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 la collecte () 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)
    ))
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X