从语法上来看,协程和生成器类似,都是在定义体中包含yield关键字的函数
但在
协程中yield关键字通常出现在表达式的右边:
- 可以产出值n(y = yield n)
- 也可以不产出值(y = yield),或者说是产出值为None
通过
next(coroutine)函数
激活协程:- 调用next(),返回 yield右边的可有可无的值或者函数值( 一般不需要next产出值,即, yield后无值,= yield ), 暂停
是通过
send(datum=None)的方式把数据提供给协程使用:
- send(n)函数的返回值为 yield右边的值或者函数值
- 等号左边的变量接受send(n)函数传来的值
- 可以理解为 函数next()和函数send(n)都 会执行yield右边的 值或者函数值,
- 但是 , send(n)函数执行完 不会暂停 ,同时send(n)函数的 参数n会赋值给等号左边的变量
def
这里的对应于
send(n)的操作 y
= yield实际上是
按2步进行的- 第1步yield 接受send(n)函数传来的参数值 , 并赋值 给 等号=左边 的变量,即y=n
- 第2步执行 yield后面的表达式或者函数并返回值
为了查看协程在运行过程中的四个状态,我们引入
from inspect import getgeneratorstate- GEN_CREATED :生成器创建完成,等待执行,可以理解为线程的就绪状态
- GEN_RUNNING :一般看不到,可理解为线程的执行状态
- GEN_SUSPENDED :在yield表达式处暂停,可理解为线程的阻塞状态
- GEN_CLOSED :执行结束,可理解为线程的死亡状态
获取协程的返回值
- 从异常属性中获取:协程结束时会跟生成器一样抛出StopIteration的异常, 返回值 就在异常对象的 value 属性中
- yield from内部会自动捕获 后面 协程StopIteration异常,并把异常对象的value属性变成yield from的返回值
- yield from 的主要功能就是打开双向通道,最外层的调用方调用 子生成器 ,同时子生成器也可使用yield from调用另一个子生成器,一直嵌套调用 直到遇到yield 表达式结束
- send(n) 发送的值n通过yield from直接传递给了 最内层的子生成器 ,并在yield from处等待子生成器的返回
丛异常中获取协程返回值(1)
丛异常中获取协程返回值(2)
异步IO(asyncio)
- Python 3.4版本引入 异步IO的标准库asyncio, 使用事件循环 驱动协程 实现并发。
- 在asyncio库中, 用asyncio.coroutine装饰 , 用yield from来驱动协程
- Python 3.5版本中 用async代替了 asyncio.coroutine,用 await代替了 yield from
下面展示了Python 3.4中标准库
asyncio中协程(coroutine)的应用
import threading importasyncio
@asyncio.coroutine
def hello():
print('Hello world! (%s)' % threading.currentThread())
yield fromasyncio.sleep(1)
print('Hello again! (%s)' % threading.currentThread())
loop = asyncio.get_event_loop()
tasks = [hello(), hello()]
loop.run_until_complete(asyncio.wait(tasks))
loop.close()
asynciowww.liaoxuefeng.com