Asyncio.gather vs asyncio.czekaj.
asyncio.gather
oraz asyncio.wait
wydaje się, że mają podobne zastosowania: mam kilka asynchronicznych rzeczy, które chcę wykonać/poczekać (niekoniecznie czekając na zakończenie przed następnym uruchomieniem). Używają innej składni i różnią się kilkoma szczegółami, ale wydaje mi się bardzo Nie-pythoniczne mieć 2 funkcje, które mają tak ogromne nakładanie się funkcjonalności. Co przegapiłem?
3 answers
Chociaż podobne w ogólnych przypadkach ("Uruchom i uzyskaj wyniki dla wielu zadań"), każda funkcja ma jakąś specyficzną funkcjonalność dla innych przypadków:
asyncio.gather()
Zwraca przyszłą instancję, umożliwiając grupowanie zadań na wysokim poziomie:
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)
Wszystkie zadania w grupie mogą być anulowane przez wywołanie group2.cancel()
lub nawet all_groups.cancel()
. Zobacz też .gather(..., return_exceptions=True)
,
asyncio.wait()
Obsługuje oczekiwanie na zatrzymanie po wykonaniu pierwszego zadania lub po określonym czasie, umożliwiając precyzja operacji niższego poziomu:
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()
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-15 10:33:27
asyncio.wait
jest bardziej niski niż asyncio.gather
.
Jak sama nazwa wskazuje, asyncio.gather
skupia się głównie na zbieraniu wyników. czeka na kilka futures i zwraca ich wyniki w danej kolejności.
asyncio.wait
tylko czeka na przyszłość. i zamiast dawać wyniki bezpośrednio, daje gotowe i oczekujące zadania. musisz manierystycznie zbierać wartości.
Ponadto, można określić, aby czekać na wszystkie futures do końca lub tylko pierwszy z wait
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-10 14:03:41
Zauważyłem również, że możesz podać grupę coroutines w wait (), po prostu podając listę:
result=loop.run_until_complete(asyncio.wait([
say('first hello', 2),
say('second hello', 1),
say('third hello', 4)
]))
Podczas gdy grupowanie w gather() odbywa się poprzez podanie wielu koroutinów:
result=loop.run_until_complete(asyncio.gather(
say('first hello', 2),
say('second hello', 1),
say('third hello', 4)
))
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-30 16:31:07