Python Asyncio.gather 与 asyncio.wait

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/42231161/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 21:26:44  来源:igfitidea点击:

Asyncio.gather vs asyncio.wait

pythonpython-asyncio

提问by Claude

asyncio.gatherand asyncio.waitseem to have similar uses: I have a bunch of async things that I want to execute/wait for (not necessarily waiting for one to finish before the next one starts). They use a different syntax, and differ in some details, but it seems very un-pythonic to me to have 2 functions that have such a huge overlap in functionality. What am I missing?

asyncio.gather并且asyncio.wait似乎有类似的用途:我有一堆异步的东西要执行/等待(不一定要在下一个开始之前等待一个完成)。它们使用不同的语法,并且在一些细节上有所不同,但对我来说,拥有 2 个在功能上有如此巨大重叠的函数似乎非常不符合 Python 风格。我错过了什么?

回答by Udi

Although similar in general cases ("run and get results for many tasks"), each function has some specific functionality for other cases:

尽管在一般情况下类似(“运行并获得许多任务的结果”),但每个函数对于其他情况都有一些特定的功能:

asyncio.gather()

asyncio.gather()

Returns a Future instance, allowing high level grouping of tasks:

返回一个 Future 实例,允许对任务进行高级分组:

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)

All tasks in a group can be cancelled by calling group2.cancel()or even all_groups.cancel(). See also .gather(..., return_exceptions=True),

一个组中的所有任务都可以通过调用group2.cancel()或取消all_groups.cancel()。另见.gather(..., return_exceptions=True)

asyncio.wait()

asyncio.wait()

Supports waiting to be stopped after the first task is done, or after a specified timeout, allowing lower level precision of operations:

支持在第一个任务完成后或指定超时后等待停止,允许较低级别的操作精度:

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

回答by ospider

asyncio.waitis more low level than asyncio.gather.

asyncio.wait比 低asyncio.gather

As the name suggests, asyncio.gathermainly focuses on gathering the results. it waits on a bunch of futures and return their results in a given order.

顾名思义,asyncio.gather主要侧重于收集结果。它等待一堆期货并按给定顺序返回它们的结果。

asyncio.waitjust waits on the futures. and instead of giving you the results directly, it gives done and pending tasks. you have to mannually collect the values.

asyncio.wait只等期货。它不会直接为您提供结果,而是提供已完成和待处理的任务。您必须手动收集值。

Moreover, you could specify to wait for all futures to finish or the just the first one with wait.

此外,您可以指定等待所有期货完成或仅等待第一个带有wait.

回答by Johny Ebanat

I also noticed that you can provide a group of coroutines in wait() by simply specifying the list:

我还注意到你可以通过简单地指定列表在 wait() 中提供一组协程:

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

Whereas grouping in gather() is done by just specifying multiple coroutines:

而在 gather() 中的分组只是通过指定多个协程来完成的:

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