为何你还不懂得如何使用Python协程
关于我
一个有思想的程序猿,终身学习实践者,目前在一个创业团队任team lead,技术栈涉及Android、Python、Java和Go,这个也是我们团队的主要技术栈。
Github:https://github.com/hylinux1024
微信公众号:终身开发者(angrycode)
在前一篇《一文彻底搞懂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
)是在线程中执行的,可理解为微线程,但协程的切换没有上下文的消耗,它比线程更加轻量些。一个协程可以随时中断自己让另一个协程开始执行,也可以从中断处恢复并继续执行,它们之间的调度是由程序员来控制的(可以看本文开篇处生产者-消费者的代码)。
定义一个协程
在Python
3.5+版本新增了aysnc
和await
关键字,这两个语法糖让我们非常方便地定义和使用协程。
在函数定义时用async
声明就定义了一个协程。
import asyncio # 定义了一个简单的协程 async def simple_async(): print('hello') await asyncio.sleep(1) # 休眠1秒 print('python') # 使用asynio中run方法运行一个协程 asyncio.run(simple_async()) # 执行结果为 # hello # python
在协程中如果要调用另一个协程就使用await
。要注意