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?
Réponses
Trop de publicités?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()
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
.
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)
))