2017-02-14 13 views
34

asyncio.gather i asyncio.wait wydają się mieć podobne zastosowania: Mam kilka asynchronicznych rzeczy, które chcę wykonać/czekać (niekoniecznie czekając na zakończenie, zanim zacznie się następny). Używają innej składni i różnią się pewnymi szczegółami, ale wydaje mi się bardzo nieprecyzyjna, że ​​mam 2 funkcje, które mają tak wielkie nakładanie się funkcji. czego mi brakuje?Asyncio.gather vs asyncio.wait

Odpowiedz

41

Chociaż podobne w ogólnych przypadkach („biegać i uzyskać wyniki do wielu zadań”), każda funkcja ma pewną specyficzną funkcjonalność dla pozostałych przypadkach:

asyncio.gather()

Zwraca Future instancji, umożliwiając wysoką grupowanie poziomowego zadania:

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) 

wszystkich zadań w grupie może być anulowana przez wywołanie group2.cancel() lub nawet all_groups.cancel(). Zobacz także .gather(..., return_exceptions=True),

asyncio.wait()

Obsługuje czeka być zatrzymany po pierwszym zadaniem jest zrobione, albo po upływie określonego limitu czasu, dzięki czemu dokładność niższy poziom operacji:

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

"Pojedyncza forma gwiazdki (* args) służy do przekazania listy argumentów o zmiennej długości, która nie jest słowami kluczowymi, a formularz podwójnej gwiazdki służy do przekazywania listy argumentów o zmiennej długości słów kluczowych" – laycat

6

asyncio.wait jest bardziej niski poziom niż asyncio.gather.

Zgodnie z nazwą, asyncio.gather skupia się głównie na zbieraniu wyników. czeka na wiele przyszłości i zwraca wyniki w określonej kolejności.

asyncio.wait tylko czeka na futures. i zamiast dawać wyniki bezpośrednio, daje on gotowe i oczekujące zadania. musisz ręcznie zbierać wartości.

Co więcej, można określić oczekiwanie na zakończenie wszystkich kontraktów terminowych lub właśnie ten pierwszy z wait.

2

Zauważyłem również, że można podać grupę współprogram w wait() po prostu określając listę:

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

co następuje grupowanie się zebrać() odbywa się tylko z podaniem wielu współprogram:

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