Python3如何asyncio.gather()部分函数列表

时间:2019-01-21 13:24:00

标签: python-3.x python-asyncio

我正在尝试创建一个可以传递给asyncio.gather()的协程列表

但是,我想在将这些协程添加到列表时将参数附加到这些协程。

下面显示的当前方法使用functools.partial。不幸的是asyncio.gather不接受部分函数,​​这很有意义。

对我来说没有意义的是如何找到解决方案。

示例代码:

async def test(arg1):
    print(arg1)

statements = []

function = functools.partial(test, "hello world")
statements.append(function)

results = await asyncio.gather(*statements)

那么我如何将参数附加到函数,以便仍可以将其传递给asyncio.gather?

*编辑

看来我很傻。

我的解决方案非常简单,不要使用functools.partial,而是将协程直接添加到列表中。

代码:

async def test(arg1):
    print(arg1)

async def main():
    statements = []
    statements.append(test("hello_world"))
    results = await asyncio.gather(*statements)

loop = asyncio.get_event_loop()
loop.run_until_complete(main())

2 个答案:

答案 0 :(得分:7)

多个异步函数调用的结果只收集一次

如果你只需要运行一次 async 函数调用序列,你可以简单地将它们立即返回的协程对象存储在一个列表中,将解压后的列表传递给 asyncio.gather 然后 {{1} } 收集协程的最终返回值。

await

这是可行的,因为与普通函数不同,调用 async def upper_cased(value: str) -> str: await asyncio.sleep(1) return value.upper() coroutines = [ upper_cased("h"), upper_cased("e"), upper_cased("l"), upper_cased("l"), upper_cased("o"), upper_cased(" "), upper_cased("w"), upper_cased("o"), upper_cased("r"), upper_cased("l"), upper_cased("d"), ] print("".join(await asyncio.gather(*coroutines))) # prints HELLO WORLD 函数(不等待)不会开始执行它,它只是返回一个对象,其中包含函数调用的所有必要细节,包括参数值。稍后可以使用此对象以不同方式完成其执行,其中之一是使用 async

多次收集多个异步函数调用的结果

如果您需要运行相同的 await 函数序列(带有预定参数)多次,只需将它们的返回值存储在一个列表中,然后将解压后的列表传递给 {{ 1}} 不起作用

这是因为协程对象只能等待一次。当它们已经返回值时再次等待它们将引发 async

asyncio.gather

对于这种情况,您可以使用 RuntimeError 对象来存储 async def random_cased(value: str) -> str: await asyncio.sleep(1) if random.randint(0, 1) == 1: return value.upper() return value.lower() coroutines = [ random_cased("h"), random_cased("e"), random_cased("l"), random_cased("l"), random_cased("o"), random_cased(" "), random_cased("w"), random_cased("o"), random_cased("r"), random_cased("l"), random_cased("d"), ] print("".join(await asyncio.gather(*coroutines))) # prints HeLlO wOrLd (or any other random cased variation) print("".join(await asyncio.gather(*coroutines))) # raises RuntimeError (cannot reuse already awaited coroutine) 函数及其参数值。

functools.partial

如果需要,您也可以使用其他容器代替 async。例如,一个用于存储函数的列表和另一个用于存储其参数的列表。

答案 1 :(得分:1)

  

但是,我想在将这些协程添加到列表时将参数附加到这些协程。

您可以简单地通过必要的参数调用协程函数。与普通函数(但类似于生成器)不同,调用协程函数不会开始执行它,它只是返回一个对象,该对象可用于稍后驱动它的执行。该对象已经捕获了调用参数,可以将其添加到传递给asyncio.gather的列表中。

例如:

statements = []

statements.append(test("hello world"))
# ...

results = await asyncio.gather(*statements)