为什么你还不懂得怎么使用为什么你还不懂得怎么使用Python协程协程
前言前言
从语法上来看,协程和生成器类似,都是定义体中包含yield关键字的函数。
yield在协程中的用法:
在协程中yield通常出现在表达式的右边,例如:datum = yield,可以产出值,也可以不产出–如果yield关键字后面没有表达式,
那么生成器产出None.
协程可能从调用方接受数据,调用方是通过send(datum)的方式把数据提供给协程使用,而不是next(…)函数,通常调用方会
把值推送给协程。
协程可以把控制器让给中心调度程序,从而激活其他的协程
所以总体上在协程中把yield看做是控制流程的方式。
在前一篇《一文彻底搞懂Python可迭代(Iterable)、迭代器(Iterator)和生成器(Generator)的概念》 的文中,知道生成器
(Generator)可由以下两种方式定义:
列表生成器
使用yield定义的函数
在Python早期的版本中协程也是通过生成器来实现的,也就是基于生成器的协程(Generator-based Coroutines)。在前一篇
介绍生成器的文章末尾举了一个生产者-消费者的例子,就是基于生成器的协程来实现的。
def producer(c):
n = 0
while n < 5:
n += 1
print('producer {}'.format(n))
r = c.send(n)
print('consumer return {}'.format(r))
def consumer():
r = ''
while True:
n = yield r
if not n:
return
print('consumer {} '.format(n))
r = 'ok'
if __name__ == '__main__':
c = consumer()
next(c) # 启动consumer
producer(c)
看了这段代码,相信很多初学者和我一样对基于生成器的协程实现其实很难马上就能够根据业务写出自己的协程代码。
Python实现者们也注意到这个问题,因为它太不Pythonic了。而基于生成器的协程也将被废弃,因此本文将重点介绍asyncio
包的使用,以及涉及到的一些相关类概念。
注:注:我使用的Python环境是3.7。
0x00 何为协程何为协程(Coroutine)
协程(Coroutine)是在线程中执行的,可理解为微线程,但协程的切换没有上下文的消耗,它比线程更加轻量些。一个协程可以
随时中断自己让另一个协程开始执行,也可以从中断处恢复并继续执行,它们之间的调度是由程序员来控制的(可以看本文开
篇处生产者-消费者的代码)。
定义一个协程定义一个协程
在Python3.5+版本新增了aysnc和await关键字,这两个语法糖让我们非常方便地定义和使用协程。
在函数定义时用async声明就定义了一个协程。
import asyncio
# 定义了一个简单的协程
async def simple_async():
print('hello')
await asyncio.sleep(1) # 休眠1秒