在 Python 中,异步 IO 是一种高效的并发处理方式。简单来说,当你发起一个 IO 操作时,不需要等待它结束,可以继续做其他事情,当操作完成时会收到通知。
Asyncio 是 Python 实现并发(concurrency)的一种方式。虽然线程(threading)和多进程(multiprocessing)也能实现并发,但 Asyncio 更侧重于 I/O 密集型任务。需要注意的是,由于 GIL(全局解释器锁)的存在,Python 的多线程并不能带来真正的并行(parallelism),而 Asyncio 同样无法绕过这一限制,但它通过单线程协作式调度实现了高吞吐。
可交给 asyncio 执行的任务称为协程(coroutine)。一个协程可以主动放弃执行权,把机会让给其它协程,这通常通过 yield from 或 await 关键字实现。
1. 协程的定义
定义协程需要使用 async def 语句。
async def do_some_work(x):
pass
此时 do_some_work 是一个协程函数,可以通过 asyncio.iscoroutinefunction 来验证:
print(asyncio.iscoroutinefunction(do_some_work)) # True
为了模拟实际工作量,我们让它睡眠几秒:
async def do_some_work(x):
print("Waiting " + str(x))
await asyncio.sleep(x)
在深入 await 之前,需要明确协程能做什么:
- 等待一个 future 结束
- 等待另一个协程(产生结果或引发异常)
- 向等待它的协程返回结果
- 向等待它的协程抛出异常
asyncio.sleep 本身也是一个协程,所以 await asyncio.sleep(x) 本质上是等待另一个协程完成。
2. 运行协程
调用协程函数并不会立即开始运行,只是返回一个协程对象。可以通过 asyncio.iscoroutine 验证:
print(asyncio.iscoroutine(do_some_work(3))) # True
如果不调用 await 直接忽略这个对象,会触发警告:
RuntimeWarning: coroutine 'do_some_work' was never awaited
要让协程对象真正运行,有两种方式:
- 在另一个已运行的协程中使用
await等待它。 - 通过
ensure_future函数计划它的执行。


