本文首先对asyncio模块的使用进行简单的介绍,然后着重分析asyncio中关于事件循环和协程的部分,而对于模块中在事件循环创建套接字连接等方法将会在另外的文章介绍
简单使用
async def语句或使用@asyncio.coroutine装饰的生成器来实现可以使用asyncio模块的协程
基于生成器的协程应该使用yield from 而不是原始的yield语法
import asyncio
@asyncio.coroutine
def hello():
print("Hello world!")
r = yield from asyncio.sleep(1) #asyncio.sleep(1)是一个协程,在这里可以看成一个耗时1秒的IO操作
print("Hello again!")
loop = asyncio.get_event_loop() #获取当前上下文的事件循环对象
loop.run_until_complete(hello()) #运行事件循环,等待协程完成
loop.close() #关闭事件循环
@asyncio.coroutine装饰器把一个生成器函数标记为协程函数
yield from 等待asyncio.sleep(1)协程的完成,在此期间,主线程并未等待,而是去执行事件循环中其他可以执行的协程,因此可以实现并发执行。
在Python3.5中加入了新的语法async/await,分别用于替换@asyncio.coroutine和yield from
需要注意@asyncio.coroutine/yield from 和async/await两种方式不能混用
可以在在事件循环中执行多个协程
tasks = [hello(), hello()]
loop.run_until_complete(asyncio.wait(tasks))
协程Coroutine
名词解释
首先我们区分一下,将yield语句放置在赋值符号右边的生成器可以被称为协程,而使用async def定义 或@asyncio.coroutine修饰的函数也可以称为协程,但是后者是可以使用asyncio模块的Coroutine协程类型
同样"协程"一词可以用来指协程函数和协程对象。
协程函数 就是使用async def或用@asyncio.coroutine装饰的函数,可以使用asyncio.iscoroutinefunction(func)来判断
协程对象 就是通过调用协程函数获得的对象,可以使用asyncio.iscoroutine(obj)来判断
协程函数中通常由两种方式来结束执行
return expression 为通过await或yield from生成结果
raise expression 生成异常
在事件循环中轮询的对象都是Future对象,Task为Future的子类,也可在事件循环中,通常Future和Task没有什么本质区别,可以混用
Future对象是指添加到事件循环中,将要通过执行来生成结果或抛出异常的对象
Future对象在事件事件循环中通常由两种方式出现
使用在result = await/yield from future表达式中,挂起当前协程等待future完成,返回future结果或抛出异常,这两个都能传播
如果future被取消(future.canael()),那么抛出asyncio.CanceledError异常
使用loop.create_task()或asyncio.ensure_future()或loop.create_future()将future注册到事件循环中
这个两个可以联合使用 result = await asyncio.ensure_future(cor),将coroutine转换为future对象,注册到事件循环,然后再挂起当前的协程,等待future完成返回结果
Coroutine对象以两种方式启动
调用协程并不会启动其代码运行,调用返回的协程对象在安排运行之前不会执行任何操作
使用在result = await/yield from coroutine表达式中,当前协程等待另一个协程返回生产结果或抛出异常