Ввода-вывода.собрать против ввода-вывода.ждать
asyncio.gather
и asyncio.wait
похоже, что у меня есть аналогичное использование: у меня есть куча асинхронных вещей, которые я хочу выполнить/подождать (не обязательно ждать, пока один из них закончится до начала следующего). Они используют различный синтаксис, и отличаются в некоторых деталях, но, похоже, очень ООН-подходящие для Python для меня есть 2 функции, которые имеют такую огромную работу. Чего мне не хватает?
3 ответа:
хотя подобные в общих случаях ("запуск и получение результатов для многих задач"), каждая функция имеет определенную функциональность для других случаев:
asyncio.gather()
возвращает будущий экземпляр, позволяющий группировать задачи высокого уровня:
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)
все задачи в группе можно отменить, позвонив
group2.cancel()
или дажеall_groups.cancel()
. Смотрите также.gather(..., return_exceptions=True)
,
asyncio.wait()
поддерживает ожидание остановки после первая задача выполняется или после указанного тайм-аута, что позволяет снизить точность операций:
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
является более низким уровнем, чемasyncio.gather
.как следует из названия,
asyncio.gather
в основном фокусируется на сборе результатов. он ждет кучу фьючерсов и возвращает их результаты в заданном порядке.
asyncio.wait
просто ждет на фьючерсы. и вместо того, чтобы давать вам результаты напрямую, он дает выполненные и отложенные задачи. вы должны манерно собирать ценности.кроме того, вы можете указать, чтобы дождаться завершения всех фьючерсов или только первого с
wait
.
Я также заметил, что вы можете предоставить группу сопрограмм в ожидании (), просто указав список:
result=loop.run_until_complete(asyncio.wait([ say('first hello', 2), say('second hello', 1), say('third hello', 4) ]))
в то время как группировка в gather() выполняется путем простого указания нескольких сопрограмм:
result=loop.run_until_complete(asyncio.gather( say('first hello', 2), say('second hello', 1), say('third hello', 4) ))