在异步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()
但它按顺序执行我的任务。
等待多个等待对象的最简单方法是什么?为什么我的方法不起作用?
4条答案
按热度按时间jv4diomz1#
等效用法是使用
asyncio.gather
:为什么我的方法不起作用?
因为当你对
seq
中的每一项执行await
时,你就阻塞了协程。所以本质上,你有了伪装成异步的同步代码。如果你真的 * 想 * 这样做,你可以用loop.create_task
或asyncio.ensure_future
实现你自己的asyncio.gather
版本。编辑
最初的答案使用了较低级别的
asyncio.wait
。fzsnzjdm2#
我注意到,如果我们想要有序的结果,asyncio.gather()可能是一种比asyncio.wait()更好的等待方式。
正如文档中所指出的,asyncio.gather()方法的结果值顺序与aws中waitables的顺序一致。然而,asyncio.wait()方法的结果值顺序不会做同样的事情。您可以测试它。
5uzkadbs3#
https://docs.python.org/3/library/asyncio-task.html#asyncio.gather
asyncio.gather()
将返回每个异步函数调用的输出列表。这个方法,gather,为并发作业取任意数量的参数,而不是一个列表,所以我们解包。
在我的例子中,经常需要这个中间值
values
,而不是设计你的函数/方法来产生副作用。ix0qys7i4#
从Python 3.11开始:
异步任务组是一种更现代的并发创建和运行任务并等待其完成的方法。
...虽然,我找不到任何理由说明为什么TaskGroup应该优先于Gather