协程的演变
其实早在 Python3.4 的时候就有协程,当时的协程是通过 @asyncio.coroutine 和 yeild from 实现的。在一些很老教程中你可能看到的是下面这种形式:
import asyncio
@asyncio.coroutine
def print_hello():
print("Hello world!")
r = yield from asyncio.sleep(1)
print("Hello again!")
# 创建并获取EventLoop:
loop = asyncio.get_event_loop()
# 执行协程
loop.run_until_complete(print_hello())
loop.close()
因为现在几乎没有人这样写了,所以仅作为了解即可。
然后到了 Python3.5 引入了async/await
语法糖,一直到现在 Python 3.8 都是用这种形式来表示协程,示例如下。
import asyncio
async def print_hello():
print("Hello world!")
await asyncio.sleep(1)
print("Hello again!")
if __name__ == '__main__':
loop = asyncio.get_event_loop()
try:
print("开始运行协程")
coro = print_hello()
print("进入事件循环")
loop.run_until_complete(coro)
finally:
print("关闭事件循环")
loop.close()
这种是目前应用范围最广的,可以看到比之前的代码舒服了不少,不用再使用装饰器的形式了。
然后就到了 Python3.7 和 Python3.8,协程发生了很多细小的变化,但是最大的一个变化就是,启动协程的方法变简单了,一句就可以搞定,不用再像上面那样,创建循环然后再仍到事件循环去执行。使用 asyncio.run 这个顶级 API 就可以了。
import asyncio
async def print_hello():
print("Hello world!")
await asyncio.sleep(1)
print("Hello again!")
if __name__ == '__main__':
print("开始运行协程")
asyncio.run(print_hello())
print("进入事件循环")
怎么样是不是代码更少了,启动协程更简单了。所以这也正是我们使用 3.8 作为本教程的 Python 版,与时俱进嘛。
asyncio 的组成部分
根据目前的官方文档,总的来说分为了两部分:高层级 API 和低层级 API。
首先看高层级 API 也是接下来重点要讲的。
- 高层级 API
- 协程对象和 Tasks 对象
- 数据流
- 同步源语
- 子进程
- 队列
- 异常
- 低层级 API
- 事件循环
- Futures 对象
- 传输和协议
- 策略
- 平台支持