python 合并等待项,如Promise.all

v9tzhpje  于 2022-11-21  发布在  Python
关注(0)|答案(4)|浏览(170)

在异步JavaScript中,使用Promise.all可以很容易地并行运行任务并等待所有任务完成:

async function bar(i) {
  console.log('started', i);
  await delay(1000);
  console.log('finished', i);
}

async function foo() {
    await Promise.all([bar(1), bar(2)]);
}

// This works too:
async function my_all(promises) {
    for (let p of promises) await p;
}

async function foo() {
    await my_all([bar(1), bar(2), bar(3)]);
}

我试着用python重写后者:

import asyncio

async def bar(i):
  print('started', i)
  await asyncio.sleep(1)
  print('finished', i)

async def aio_all(seq):
  for f in seq:
    await f

async def main():
  await aio_all([bar(i) for i in range(10)])

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

但它按顺序执行我的任务。
等待多个等待对象的最简单方法是什么?为什么我的方法不起作用?

jv4diomz

jv4diomz1#

等效用法是使用asyncio.gather

import asyncio

async def bar(i):
  print('started', i)
  await asyncio.sleep(1)
  print('finished', i)

async def main():
  await asyncio.gather(*[bar(i) for i in range(10)])

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

为什么我的方法不起作用?
因为当你对seq中的每一项执行await时,你就阻塞了协程。所以本质上,你有了伪装成异步的同步代码。如果你真的 * 想 * 这样做,你可以用loop.create_taskasyncio.ensure_future实现你自己的asyncio.gather版本。

编辑

最初的答案使用了较低级别的asyncio.wait

fzsnzjdm

fzsnzjdm2#

我注意到,如果我们想要有序的结果,asyncio.gather()可能是一种比asyncio.wait()更好的等待方式。
正如文档中所指出的,asyncio.gather()方法的结果值顺序与aws中waitables的顺序一致。然而,asyncio.wait()方法的结果值顺序不会做同样的事情。您可以测试它。

5uzkadbs

5uzkadbs3#

https://docs.python.org/3/library/asyncio-task.html#asyncio.gather
asyncio.gather()将返回每个异步函数调用的输出列表。

import asyncio

async def bar(i):
    print('started', i)
    await asyncio.sleep(1)
    print('finished', i)
    return i

async def main():
    values = await asyncio.gather(*[bar(i) for i in range(10)])
    print(values)

asyncio.run(main())

这个方法,gather,为并发作业取任意数量的参数,而不是一个列表,所以我们解包。
在我的例子中,经常需要这个中间值values,而不是设计你的函数/方法来产生副作用。

ix0qys7i

ix0qys7i4#

从Python 3.11开始:
异步任务组是一种更现代的并发创建和运行任务并等待其完成的方法。
...虽然,我找不到任何理由说明为什么TaskGroup应该优先于Gather

相关问题