python之gevent模块实现协程
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模块实现协程相关推荐
- 学习笔记(35):Python网络编程并发编程-协程(yield,greenlet,gevent模块)
立即学习:https://edu.csdn.net/course/play/24458/296457?utm_source=blogtoedu 协程(yield,greenlet,gevent) 1. ...
- python正在处理中_协程和 asyncio
在本系列的 第 1 部分 中,您了解了 Python 迭代器:在 第 2 部分 中,您了解了 itertools.在这一部分,将了解一种称为协程(Coroutines)的特殊的生成器函数.您还将了解另 ...
- python 进程,线程,协程篇
python 进程,线程,协程篇 ssh 线程 进程 线程,进程区别 threading 模块,两种调用方式 python GIL全局解释器锁(Global Interpreter Lock) Joi ...
- boost::coroutine2模块实现协程的测试程序
boost::coroutine2模块实现协程的测试程序 实现功能 C++实现代码 实现功能 boost::coroutine2模块实现协程的测试程序 C++实现代码 #include <alg ...
- 基于Boost::beast模块的协程HTTP服务器
Boost:基于Boost::beast模块的协程HTTP服务器 实现功能 C++实现代码 实现功能 基于Boost::beast模块的协程HTTP服务器 C++实现代码 #include <b ...
- 基于Boost::beast模块的协程WebSocket客户端
基于Boost::beast模块的协程WebSocket客户端 实现功能 C++实现代码 实现功能 基于Boost::beast模块的协程WebSocket客户端 C++实现代码 #include & ...
- 基于Boost::beast模块的协程WebSocket 服务器
Boost:基于Boost::beast模块的协程WebSocket 服务器 实现功能 C++实现代码 实现功能 基于Boost::beast模块的协程WebSocket 服务器 C++实现代码 #i ...
- Python 线程和进程和协程总结
Python 线程和进程和协程总结 线程和进程和协程 进程 进程是程序执行时的一个实例,是担当分配系统资源(CPU时间.内存等)的基本单位: 进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其 ...
- 线程 协程 python_在Python 的线程中运行协程的方法
在一篇文章 理解Python异步编程的基本原理 这篇文章中,我们讲到,如果在异步代码里面又包含了一段非常耗时的同步代码,异步代码就会被卡住. 那么有没有办法让同步代码与异步代码看起来也是同时运行的呢? ...
最新文章
- 光耦p621引脚图_开关电源中光耦电路的设计与优点
- python web-2019年Python Web五大主流框架
- The return types for the following stored procedures could not be detected
- 使用Gatling + Gradle + Jenkins Pipeline为您的JAX-RS(和JavaEE)应用程序进行连续压力测试...
- python中的__slots__
- Vista修改默认字体
- 野火开发版屏幕_鸿蒙2.0手机开发者版发布,华为多数自研设备明年升级鸿蒙
- delphi switch语句例子_「GCTT 出品」Go 系列教程——10. switch 语句
- tableView编辑
- 怎样保持sublime text3中的代码copy到CSDN中之后的漂亮的高亮
- Python画等高线以及标注
- Oracle疑问解答
- SpringBoot读取配置文件
- 日新测试软件,禁Ping多线程批量检测工具V2.6,功能强大,你值得拥有【2020.05.09日更新】...
- html多选框点击事件onclick
- 抖音视频评论获取系统,获取抖音评论的系统
- PyCharm安装教程
- 网络带宽单位转换 — MB/s、Mb/s、Mbps、Mbit/s、Kbps
- “数字孪生”语境下的城市:拼图模式与航向之争
- 移动互联网广告 全媒体广告平台怎么代理 利润点有多少