Python通过yield提供了对协程的基本支持,但是不完全。而第三方的gevent为Python提供了比较完善的协程支持。

gevent是第三方库,通过greenlet实现协程,其基本思想是:

当一个greenlet遇到IO操作时,比如访问网络,就自动切换到其他的greenlet,等到IO操作完成,再在适当的时候切换回来继续执行。由于IO操作非常耗时,经常使程序处于等待状态,有了gevent为我们自动切换协程,就保证总有greenlet在运行,而不是等待IO。

由于切换是在IO操作时自动完成,所以gevent需要修改Python自带的一些标准库,这一过程在启动时通过monkey patch完成:

from gevent import monkey; monkey.patch_socket()
import geventdef f(n): for i in range(n): print gevent.getcurrent(), i g1 = gevent.spawn(f, 5) g2 = gevent.spawn(f, 5) g3 = gevent.spawn(f, 5) g1.join() g2.join() g3.join() 

运行结果:

<Greenlet at 0x10e49f550: f(5)> 0 <Greenlet at 0x10e49f550: f(5)> 1 <Greenlet at 0x10e49f550: f(5)> 2 <Greenlet at 0x10e49f550: f(5)> 3 <Greenlet at 0x10e49f550: f(5)> 4 <Greenlet at 0x10e49f910: f(5)> 0 <Greenlet at 0x10e49f910: f(5)> 1 <Greenlet at 0x10e49f910: f(5)> 2 <Greenlet at 0x10e49f910: f(5)> 3 <Greenlet at 0x10e49f910: f(5)> 4 <Greenlet at 0x10e49f4b0: f(5)> 0 <Greenlet at 0x10e49f4b0: f(5)> 1 <Greenlet at 0x10e49f4b0: f(5)> 2 <Greenlet at 0x10e49f4b0: f(5)> 3 <Greenlet at 0x10e49f4b0: f(5)> 4 

可以看到,3个greenlet是依次运行而不是交替运行。

要让greenlet交替运行,可以通过gevent.sleep()交出控制权:

def f(n):for i in range(n): print gevent.getcurrent(), i gevent.sleep(0) 

执行结果:

<Greenlet at 0x10cd58550: f(5)> 0 <Greenlet at 0x10cd58910: f(5)> 0 <Greenlet at 0x10cd584b0: f(5)> 0 <Greenlet at 0x10cd58550: f(5)> 1 <Greenlet at 0x10cd584b0: f(5)> 1 <Greenlet at 0x10cd58910: f(5)> 1 <Greenlet at 0x10cd58550: f(5)> 2 <Greenlet at 0x10cd58910: f(5)> 2 <Greenlet at 0x10cd584b0: f(5)> 2 <Greenlet at 0x10cd58550: f(5)> 3 <Greenlet at 0x10cd584b0: f(5)> 3 <Greenlet at 0x10cd58910: f(5)> 3 <Greenlet at 0x10cd58550: f(5)> 4 <Greenlet at 0x10cd58910: f(5)> 4 <Greenlet at 0x10cd584b0: f(5)> 4 

3个greenlet交替运行,

把循环次数改为500000,让它们的运行时间长一点,然后在操作系统的进程管理器中看,线程数只有1个。

当然,实际代码里,我们不会用gevent.sleep()去切换协程,而是在执行到IO操作时,gevent自动切换,代码如下:

from gevent import monkey; monkey.patch_all()
import gevent
import urllib2def f(url): print('GET: %s' % url) resp = urllib2.urlopen(url) data = resp.read() print('%d bytes received from %s.' % (len(data), url)) gevent.joinall([ gevent.spawn(f, 'https://www.python.org/'), gevent.spawn(f, 'https://www.yahoo.com/'), gevent.spawn(f, 'https://github.com/'), ]) 

运行结果:

GET: https://www.python.org/
GET: https://www.yahoo.com/ GET: https://github.com/ 45661 bytes received from https://www.python.org/. 14823 bytes received from https://github.com/. 304034 bytes received from https://www.yahoo.com/. 

从结果看,3个网络操作是并发执行的,而且结束顺序不同,但只有一个线程。

小结

使用gevent,可以获得极高的并发性能,但gevent只能在Unix/Linux下运行,在Windows下不保证正常安装和运行。

由于gevent是基于IO切换的协程,所以最神奇的是,我们编写的Web App代码,不需要引入gevent的包,也不需要改任何代码,仅仅在部署的时候,用一个支持gevent的WSGI服务器,立刻就获得了数倍的性能提升。具体部署方式可以参考后续“实战”-“部署Web App”一节。

来源:http://www.liaoxuefeng.com/wiki/001374738125095c955c1e6d8bb493182103fac9270762a000/001407503089986d175822da68d4d6685fbe849a0e0ca35000

转载于:https://www.cnblogs.com/work115/p/5818420.html

python之gevent模块实现协程相关推荐

  1. 学习笔记(35):Python网络编程并发编程-协程(yield,greenlet,gevent模块)

    立即学习:https://edu.csdn.net/course/play/24458/296457?utm_source=blogtoedu 协程(yield,greenlet,gevent) 1. ...

  2. python正在处理中_协程和 asyncio

    在本系列的 第 1 部分 中,您了解了 Python 迭代器:在 第 2 部分 中,您了解了 itertools.在这一部分,将了解一种称为协程(Coroutines)的特殊的生成器函数.您还将了解另 ...

  3. python 进程,线程,协程篇

    python 进程,线程,协程篇 ssh 线程 进程 线程,进程区别 threading 模块,两种调用方式 python GIL全局解释器锁(Global Interpreter Lock) Joi ...

  4. boost::coroutine2模块实现协程的测试程序

    boost::coroutine2模块实现协程的测试程序 实现功能 C++实现代码 实现功能 boost::coroutine2模块实现协程的测试程序 C++实现代码 #include <alg ...

  5. 基于Boost::beast模块的协程HTTP服务器

    Boost:基于Boost::beast模块的协程HTTP服务器 实现功能 C++实现代码 实现功能 基于Boost::beast模块的协程HTTP服务器 C++实现代码 #include <b ...

  6. 基于Boost::beast模块的协程WebSocket客户端

    基于Boost::beast模块的协程WebSocket客户端 实现功能 C++实现代码 实现功能 基于Boost::beast模块的协程WebSocket客户端 C++实现代码 #include & ...

  7. 基于Boost::beast模块的协程WebSocket 服务器

    Boost:基于Boost::beast模块的协程WebSocket 服务器 实现功能 C++实现代码 实现功能 基于Boost::beast模块的协程WebSocket 服务器 C++实现代码 #i ...

  8. Python 线程和进程和协程总结

    Python 线程和进程和协程总结 线程和进程和协程 进程 进程是程序执行时的一个实例,是担当分配系统资源(CPU时间.内存等)的基本单位: 进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其 ...

  9. 线程 协程 python_在Python 的线程中运行协程的方法

    在一篇文章 理解Python异步编程的基本原理 这篇文章中,我们讲到,如果在异步代码里面又包含了一段非常耗时的同步代码,异步代码就会被卡住. 那么有没有办法让同步代码与异步代码看起来也是同时运行的呢? ...

最新文章

  1. 光耦p621引脚图_开关电源中光耦电路的设计与优点
  2. python web-2019年Python Web五大主流框架
  3. The return types for the following stored procedures could not be detected
  4. 使用Gatling + Gradle + Jenkins Pipeline为您的JAX-RS(和JavaEE)应用程序进行连续压力测试...
  5. python中的__slots__
  6. Vista修改默认字体
  7. 野火开发版屏幕_鸿蒙2.0手机开发者版发布,华为多数自研设备明年升级鸿蒙
  8. delphi switch语句例子_「GCTT 出品」Go 系列教程——10. switch 语句
  9. tableView编辑
  10. 怎样保持sublime text3中的代码copy到CSDN中之后的漂亮的高亮
  11. Python画等高线以及标注
  12. Oracle疑问解答
  13. SpringBoot读取配置文件
  14. 日新测试软件,禁Ping多线程批量检测工具V2.6,功能强大,你值得拥有【2020.05.09日更新】...
  15. html多选框点击事件onclick
  16. 抖音视频评论获取系统,获取抖音评论的系统
  17. PyCharm安装教程
  18. 网络带宽单位转换 — MB/s、Mb/s、Mbps、Mbit/s、Kbps
  19. “数字孪生”语境下的城市:拼图模式与航向之争
  20. 移动互联网广告 全媒体广告平台怎么代理 利润点有多少

热门文章

  1. 查了一晚上的资料,累啊。
  2. flutter 一个用户登录页面
  3. Okhttp使用简析——Android网络请求框架(一)
  4. ACM模板——拓扑排序
  5. Ajax补充之serialize
  6. python基础入门--input标签、变量、数字类型、列表、字符串、字典、索引值、bool值、占位符格式输出...
  7. jmeter的分布式部署
  8. jQuery插件编写基础之“又见弹窗”
  9. 第十七篇 --ANDROID DisplayManager 服务解析一
  10. 手把手教你如何在安卓平台上实现打电话发短信的功能