asyncio提供的框架以事件循环(event loop) 为中心,程序开启一个无限的循环,程序会把一些函数注册到事件循环上。当满足事件发生的时候,调用相应的协程函数。
事件循环loop调用方法loop.run_until_complete(…)驱动传入的参数,它的参数是一个future或者协程。协程、future和任务(Task)都由yield from驱动,这正是run_until_complete方法对其参数所做的事情。
yield from function句法能够防止阻塞,是因为当前协程(即包括yield from代码的委派生成器)暂停后,控制权回到事件循环手中,再去驱动其它协程; function future或协程运行结束后,把结果返回到暂停的协程(yield from自动捕获StopIteration),将其恢复,即最外层的事件循环始终可以不被阻塞,并发地调度所有协程向前推进。
Future
future是一个数据结构,表示还未完成的工作结果。事件循环可以监视Future对象是否完成。从而允许应用的一部分等待另一部分完成一些工作。
Task
Task是Future的一个子类,它知道如何包装和管理一个协程的执行。
await
await 用于挂起阻塞的异步调用,用于挂起耗时的操作。
使用await可以针对耗时的操作进行挂起,就像生成器里的yield一样,函数让出控制权。协程遇到await,事件循环将会挂起该协程,执行await 后面跟着的那个协程,直到await来的协程也挂起或者执行完毕,再进行下一个协程的执行。
import asyncio
# async关键字定义一个协程(coroutine),协程也是一种对象。
# 协程不能直接运行,需要把协程加入到事件循环(loop)
async def func(n):
print('Hello world <{}>'.format(n))
r = await asyncio.sleep(n)
print('hello again <{}>'.format(n))
# asyncio.get_event_loop 方法可以创建一个事件循环。
loop = asyncio.get_event_loop()
# run_until_complete 将协程注册到事件循环,并启动事件循环。
# loop.run_until_complete(func(6))
tasks = [func(4), func(5), func(2)]
loop.run_until_complete(asyncio.wait(tasks))
loop.close()
"""
Hello world <5>
Hello world <2>
Hello world <4>
hello again <2>
hello again <4>
hello again <5>
"""