1.为什么要引入协程?
为了要完成异步 IO,就是你发起一个 IO 操作,却不用等它结束,你可以继续做其他事情,当它结束时,你会得到通知。它比线程所消耗的资源更少,往往是构建IO密集型的最佳选择。Python中异步编程需要使用到Asyncio。
2.基础概念:
(1)Event loop-----事件循环
Eventloop可以当作是中央总控,提供了注册、取消、执行任务和回调的方法。
我们通过把一些异步函数注册到这个事件循环上,事件循环会循环执行这些函数(注意每时刻只能执行一个函数),当执行到某个函数时,如果它正在等待I/O返回,事件循环会暂停它的执行去执行其他的函数;当某个函数完成I/O后会恢复,下次循环到它的时候继续执行。
(2)Coroutine-----协程
Coroutine本质上是一个函数,只是在该函数前加上了async关键字,如:
async def A():
await asyncio.sleep(1) #使用async方式的I/O阻塞
print("Hello World")
async def main():
Coroutine_A = A()
asyncio.run(main())
此时称Coroutine_A为一个Coroutine,注意此时不会有任何的输出,因为Event loop中的Coroutine对象不会主动执行
(3)Task-----任务
1⃣️当一个Coroutine前面声明await时,该Coroutine就变成一个Task
2⃣️通过 asyncio.create_task(),将Coroutine变成一个Task
async def A():
await asyncio.sleep(1)
print("Hello World")
async def main():
Task_A = await A() #一般不采用第一种方式
Task_B = asyncio.create_task(A())
await Task_A #将Task_A注册到Eventloop中
await Task_B #将Task_B注册到Eventloop中
asyncio.run(main())
此时称Task_A、Task_B均为一个Task,程序返回值为
Hello World. Hello World
在Event loop队列中,Coroutine不会主动执行,只有变成Task后,才会运行内部的代码
可以看出,如果有多个对象需要注册到Event loop中时,代码就会显得很繁琐,这时候就需要用到gather来返回一个Future对象列表
(4)Future
它代表了一个「未来」对象,异步操作结束后会把最终结果设置到这个Future对象上。
async def A(what):
await asyncio.sleep(1)
return f"{what}"
async def main():
Task_A = asyncio.create_task(A("Hello"))
Task_B = asyncio.create_task(A("World"))
ret = await asyncio.gather(Task_A,Task_B)
asyncio.run(main())
此时的返回值为[“Hello”,“World”]