asyncio.gather(tasks1, task2, ...)
的作用:
举个例子:
import asyncio
async def func1():
print('func1 started')
await asyncio.sleep(2)
return 'result of func1'
async def func2():
print('func2 started')
await asyncio.sleep(3)
return 'result of func2'
async def main():
res = await asyncio.gather(func1(), func2())
print(res)
asyncio.run(main())
func1 started
func2 started
['result of func1', 'result of func2']
在这个例子里面, 我们定义的都是异步函数, 调用asynico.run
来使整个程序run
起来, 不然还需要我们手动的send(None)
来执行代码, asyncio.run()
内部会先创建一个事件循环,然后执行main()
协程, 在这里使用了很多的await
, 再次理解是 : await
相当于递归进去, 让你先去执行这个await
里面的东西, 等你执行完了再把值返回回来.
然后我们再理解下run
在干什么, 他会一直run
直到遇见StopIteration
, 伪代码如下:
while True:
try:
x = self.coro.send(None)
except StopIteration as e:
result = e.value
else:
func, arg = x
func(arg)
而后面的着一个部分func(arg)
正是完成最底层的那个任务的需求, 最底层可以使用一个awaitable
的一个对象, 然后使用: await Awaitable((function, args))
, 这个时候最底层函数释放执行权, 将执行权交给顶层函数, 顶层函数执行完了之后再send(None)
下来, 继续完成后续的操作, 如果有返回值的话就返回值, 和递归很像, 但是递归强调的是分解任务, 而协程强调的是协作, 可以等, 并且让出执行权.
然后接着代码, 这里是res
等于gather
最终的返回值, 所以要先等到gather
的运行结束, 然后gather
调用两个func
, 等到两个func
都执行结束, 返回值交给res
, 虽然一个需要 2 s 2s 2s一个需要 3 s 3s 3s但是gather
会等到所有都结束了再传给res
, 相当于省下了写join
, 非常的方便