本文摘自php中文网,作者零到壹度,侵删。
本篇文章给大家分享的内容是深入了解python中的协程函数 ,有着一定的参考价值,有需要的朋友可以参考一下
概念:
根据维基百科给出的定义,“协程 是为非抢占式多任务产生子程序的计算机程序组件,协程允许不同入口点在不同位置暂停或开始执行程序”。从技术的角度来说,“协程就是你可以暂停执行的函数”。如果你把它理解成“就像生成器一样”,那么你就想对了。
协程,又称为微线程,看上去像是子程序,但是它和子程序又不太一样,它在执行的过程中,可以在中断当前的子程序后去执行别的子程序,再返回来执行之前的子程序,但是它的相关信息还是之前的。
协程不同于线程,线程是抢占式的调度,而协程是协同式的调度,协程需要自己做调度。
子程序调用总是一个入口,一次返回,调用顺序是明确的。而协程的调用和子程序不同。协程看上去也是子程序,但执行过程中,在子程序内部可中断,然后转而执行别的子程序,在适当的时候再返回来接着执行。
协程的优点:
协程优势是极高的执行效率。因为子程序切换不是线程切换,而是由程序自身控制,因此,没有线程切换的开销,和多线程比,线程数量越多,协程的性能优势就越明显。用来执行协程多任务非常合适。
协程没有线程的安全问题。一个进程可以同时存在多个协程,但是只有一个协程是激活的,而且协程的激活和休眠又是程序员通过编程来控制,而不是操作系统控制的。
生成器实现协程原理
示例:
1 2 3 4 5 6 7 8 9 10 |
|
输出打印:1task------5
解释说明:
很明显func是一个生成器,send方法有一个参数,该参数指定的是上一次被挂起的yield语句的返回值。
send需要做异常处理。
总的来说,send方法和next方法唯一的区别是在执行send方法会首先把上一次挂起的yield语句的返回值通过参数设定,从而实现与生成器方法的交互。但是需要注意,在一个生成器对象没有执行next方法之前,由于没有yield语句被挂起,所以执行send方法会报错。
send方法的参数为None时,它与next方法完全等价。
生成器实现生产者和消费者模式:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
1 2 3 4 5 6 7 8 9 10 11 |
|
解释说明:
在生产者里先执行了 c.send(None),目的是先让消费者挂起,再用send传值,第一次传1,消费者那里打印1,生产者打印r是消费者yield后面的值。
greenlet 的引入
虽然CPython(标准Python)能够通过生成器来实现协程,但使用起来还并不是很方便。
与此同时,Python的一个衍生版 Stackless Python实现了原生的协程,它更利于使用。
于是,大家开始将 Stackless 中关于协程的代码 单独拿出来做成了CPython的扩展包。
这就是 greenlet 的由来,因此 greenlet 是底层实现了原生协程的 C扩展库。
代码示意:
1 2 3 4 5 6 7 8 9 10 11 12 |
|
greenlet 的价值:
高性能的原生协程
语义更加明确的显式切换
直接将函数包装成协程,保持原有代码风格
gevent协程
虽然,我们有了 基于 epoll 的回调式编程模式,但是却难以使用。
即使我们可以通过配合 生成器协程 进行复杂的封装,以简化编程难度。
但是仍然有一个大的问题: 封装难度大,现有代码几乎完全要重写
gevent,通过封装了 libev(基于epoll) 和 greenlet 两个库。
帮我们做好封装,允许我们以类似于线程的方式使用协程。
以至于我们几乎不用重写原来的代码就能充分利用 epoll 和 协程 威力。
代码示意:
1 2 3 4 5 6 7 8 |
|
gevent 的价值:
遇到阻塞就切换到另一个协程继续执行 !
使用基于 epoll 的 libev 来避开阻塞。
使用基于 gevent 的 高效协程 来切换执行。
只在遇到阻塞的时候切换,没有轮需的开销,也没有线程的开销。
gevent实现并发服务器
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
gevent 协程通信
gevent也有自己的队列。使用方式和进线程基本一样。
基于gevent和队列的生产者和消费者模式
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
1 2 |
|
相关推荐:
python中多进程+协程的使用
python中协程
Python 协程的详细用法和例子
python 协程示例
以上就是深入了解python中的协程函数的详细内容,更多文章请关注木庄网络博客!!
相关阅读 >>
更多相关阅读请进入《Python》频道 >>

Python编程 从入门到实践 第2版
python入门书籍,非常畅销,超高好评,python官方公认好书。