gevent简介
gevent是基于协程的Python网络库。
协程存在的意义:对于多线程应用,CPU通过切片的方式来切换线程间的执行,线程切换时需要耗时(保存状态,下次继续)。协程,则只使用一个线程,在一个线程中规定某个代码块执行顺序,当程序中存在大量不需要CPU的操作时(IO),适用于协程。
特点:基于libev的快速事件循环(Linux上epoll,FreeBSD上kqueue),基于greenlet的轻量级执行单元。而且其中有个monkey类,将现有基于Python线程直接转化为greenlet(类似于打patch)。
libev:libev是libevent之后的一个事件驱动的编程框架,其接口和libevent基本类似。据官方介绍,其性能比libevent还要高,bug比libevent还少。Libev通过一个structev_loop结构表示一个事件驱动的框架。在这个框架里面通过ev_xxx结构,ev_init、ev_xxx_set、ev_xxx_start接口向这个事件驱动的框架里面注册事件监控器,当相应的事件监控器的事件出现时,便会触发该事件监控器的处理逻辑,去处理该事件。处理完之后,这些监控器进入到下一轮的监控中。而libevent是一个事件触发的网络库,适用于windows、linux、bsd等多种平台,内部使用select、epoll、kqueue、IOCP等系统调用管理事件机制,libevent支持用户使用三种类型的事件,分别是网络IO、定时器、信号三种,Libev 除了提供了基本的三大类事件(IO事件、定时器事件、信号事件)外还提供了周期事件、子进程事件、文件状态改变事件等多个事件,libevent支持多线程编程,每个事件需要关联到自己的event_base。
greenlet:指的是使用一个任务调度器和一些生成器或者协程实现协作式用户空间多线程的一种伪并发机制,即所谓的微线程。主要思想是:生成器函数或者协程函数中的yield语句挂起函数的执行,直到稍后使用next()或send()操作进行恢复为止。可以使用一个调度器循环在一组生成器函数之间协作多个任务。greenlet不是一种真正的并发机制,而是在同一线程内,在不同函数的执行代码块之间切换,实施“你运行一会、我运行一会”,并且在进行切换时必须指定何时切换以及切换到哪,因此,greenlet本质是一种合理安排了的串行。
monkey patch:在最开头的地方gevent.monkey.patch_all();把标准库中的thread/socket等给替换掉.这样我们在后面使用socket的时候可以跟平常一样使用,无需修改任何代码,如果不进行 monkey patch,会造成严重后果,性能下降,数据错误,代码切换异常等。
要想理解gevent首先要理解gevent的调度流程,gevent中有一个hub的概念,也就是MainThread,用于调度所有其它的greenlet实例。

每次从hub切换到一个greenlet后,都会回到hub,这就是gevent的关键,gevent中并没有greenlet链的说法,所有都是向主循环注册greenlet.switch方法,主循环在合适的时机切换回来。为什么每次都要切换到hub呢?
1.hub是事件驱动的核心,每次切换到hub后将继续循环事件。如果在一个greenlet中不出来,那么其它greenlet将得不到调用。
2.维持两者关系肯定比维持多个关系简单。每次我们所关心的就是hub以及当前greenlet,不需要考虑各个greenlet之间关系。
下面看一个简单的gevent的例子:

我们对这段小代码进行debug,然后在控制台查看线程数:

只有一个线程,他run的其实是greenlet这个伪线程。

然后看执行结果:

我们用显式的sleep使其进行切换,可以看到在sleep后,代码切换到了其他greenlet,因为gevent认为此处出现了阻塞,一旦检测到阻塞,gevent就会自动进行greenlet切换。如果不进行显式调用,则greenlet其实是顺序执行的,因为本质上它是串行的,现在我们将sleep去掉,结果是这样:

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

我们没有显式的进行sleep,而是依赖各个IO操作自身的阻塞时间,下面我们看下结果:

可以看到,结束顺序和IO发起顺序并不一致。gevent.spawn()方法创建greenlet实例并调用其start方法发起,然后通过gevent.joinall将greenlet实例加入到greenlet执行队列中等待其完成,这里可以为其设置超时时间。
gevent还可以作为起celery worker和celery beat时的POOL(支持prefork (default), eventlet, gevent, solo or threads),在启动celery worker时,-P为gevent,即指定gevent为POOL。
gevent简介的更多相关文章
- gevent调度流程解析
gevent是目前应用非常广泛的网络库,高效的轮询IO库libev加上协程(coroutine),使得gevent的性能非常出色,尤其是在web应用中.本文介绍gevent的调度流程,主要包括geve ...
- Python中Paramiko协程方式详解
什么是协程 协程我们可以看做是一种用户空间的线程. 操作系统对齐存在一无所知,需要用户自己去调度. 比如说进程,线程操作系统都是知道它们存在的.协程的话是用户空间的线程,操作系统是不知道的. 为什么要 ...
- 百万年薪python之路 -- 并发编程之 协程
协程 一. 协程的引入 本节的主题是基于单线程来实现并发,即只用一个主线程(很明显可利用的cpu只有一个)情况下实现并发,为此我们需要先回顾下并发的本质:切换+保存状态 cpu正在运行一个任务,会在两 ...
- Python之路【第一篇】:Python简介和入门
python简介: 一.什么是python Python(英国发音:/ pa θ n/ 美国发音:/ pa θɑ n/),是一种面向对象.直译式的计算机程序语言. 每一门语言都有自己的哲学: pyth ...
- python gevent 协程
简介 没有切换开销.因为子程序切换不是线程切换,而是由程序自身控制,没有线程切换的开销,因此执行效率高, 不需要锁机制.因为只有一个线程,也不存在同时写变量冲突,在协程中控制共享资源不加锁,只需要判断 ...
- gunicorn 简介
gunicorn是一个python Wsgi http server,只支持在Unix系统上运行,来源于Ruby的unicorn项目.Gunicorn使用prefork master-worker ...
- Python之路【第一篇】:Python简介和入门
python简介: 一.什么是python Python(英国发音:/ pa θ n/ 美国发音:/ pa θɑ n/),是一种面向对象.直译式的计算机程序语言. 每一门语言都有自己的哲学: pyth ...
- Python之celery的简介与使用
celery的简介 celery是一个基于分布式消息传输的异步任务队列,它专注于实时处理,同时也支持任务调度.它的执行单元为任务(task),利用多线程,如Eventlet,gevent等,它们能 ...
- python 全栈开发,Day43(引子,协程介绍,Greenlet模块,Gevent模块,Gevent之同步与异步)
昨日内容回顾 I/O模型,面试会问到I/O操作,不占用CPU.它内部有一个专门的处理I/O模块.print和写log 属于I/O操作,它不占用CPU 线程GIL保证一个进程中的多个线程在同一时刻只有一 ...
随机推荐
- 6.10&&6.12考试反思
考试结果:6.10AK 6.12:100(评测机)200(本地&&兼容评测机版) OI的考试做题流程无非是: 通读全部题目——>找一个最有把握/最简单的题——>分析思考—— ...
- Linq in not in\like not like
别人的博客 http://blog.163.com/lesheng@126/blog/static/357364652010102111051668/ using System.Data.Linq.S ...
- Springboot-H2DB
为什么在Springboot中用H2DB 用Springboot开发需要连接数据库的程序的时候,使用H2DB作为内存数据库可以很方便的调试程序. 怎么用 1.加入依赖 <dependency&g ...
- shell 中使用正则表达式
ls | xargs echo | sed 's/.*\(\w\+\)\s\(\w\+\s\)*\1d.*/\1/' 说明 \w\+表示一段连续的字符串 \s\+ 一个或者多个空格 \s* 0个或者多 ...
- 《SQL Server 2012 T-SQL基础》读书笔记 - 2.单表查询
Chapter 2 Single-Table Queries GROUP BY之后的阶段的操作对象就是组(可以把一组想象成很多行组成的)了,HAVING负责过滤掉一些组.分组后的COUNT(*)表示每 ...
- Python编程:从入门到实践—函数
从函数中修改列表 一家为用户提交的设计制作3D打印模型的公司,需要打印的设计存储在一个列表中,打印后移到另一个列表中. #!/usr/bin/env python # -*- coding:utf-8 ...
- 图论之点双&边双
说人话: 边双联通: a到b的路径上无必经边 点双联通: a到b的路径上除了a,b没有必经点 tarjan求点双联通: 代码(补图) 割点: 桥: 求点双:强制dfs时不越过割点,即可求出一个块 求边 ...
- Delphi XE2 之 FireMonkey 入门(20) - TStyleBook(皮肤、样式相关)
我觉得叫 "皮肤" 不如叫 "样式" 或 "风格", 因为它可以包含和动作关联的动画. 在 FMX 下, 控件可以任意绘制, 各部件个性化的 ...
- base64编解码的两个函数
base64编解码的两个函数,声明,参考网络上的代码实现. unsigned char *base64_encode(unsigned char *str, long* lpBufLen) { lon ...
- 【ABAP系列】SAP ABAP 优化LOOP循环的一点点建议
公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[ABAP系列]SAP ABAP 优化LOOP循 ...