什么是greenlet?

虽然CPython(标准Python)能够通过生成器来实现协程,但使用起来还并不是很方便。

与此同时,Python的一个衍生版 Stackless Python实现了原生的协程,它更利于使用。

于是,大家开始将 Stackless 中关于协程的代码单独拿出来做成了CPython的扩展包。

这就是 greenlet 的由来,因此 greenlet 是底层实现了原生协程的 C扩展库

greenlet的基本使用

# 基于greenlet的生产者消费者协程
from greenlet import greenlet
import random
import time def Producer():
while True:
item = random.randint(1, 10)
print("生产<{}>中...".format(item))
time.sleep(1)
c.switch(item) # 切换到消费者,并将item传入。 def Consumer():
while True:
item = p.switch() # 切换到生产者。等待生产者传递参数item
print("消费<{}>中..".format(item)) c = greenlet(Consumer) # 将普通函数编程协程
p = greenlet(Producer) # 同理
c.switch() # 启动协程,Consumer先执行
"""
从consumer开始执行,执行到item=p.switch()时,程序切换到producer,并等待传参
producer得到执行权后,生成一个item,并往下执行代码
当producer执行到c.switch(item)时,程序携带传递的item切换到consumer,
consumer继续往下执行,直到下一次运行到p.switch时,交出执行权,切换到producer,重复以上过程 greenlet的价值在于高性能的原生协程,
且语义更加明确、显示切换
执行到switch时就切换程序
直接将函数包装成协程,可以保留原代码的风格
"""

什么是gevent?

虽然,我们有了 基于 epoll 的回调式编程模式,但是却难以使用。即使我们可以通过配合 生成器协程 进行复杂的封装,以简化编程难度。
但是仍然有一个大的问题: 封装难度大,现有代码几乎完全要重写gevent,通过封装了 libev(基于epoll) 和 greenlet 两个库。
帮我们做好封装,允许我们以类似于线程的方式使用协程。以至于我们几乎不用重写原来的代码就能充分利用 epoll 和 协程 威力。

gevent的常用操作

"""
gevent: 通过greenlet实现协程,核心就是遇到IO操作,会自动切换到其他协程 """
# 将python标准库中的一些阻塞操作变为非阻塞
from gevent import monkey;monkey.patch_all()
# 使用猴子补丁要写在第一行
import gevent def test1():
print("test1")
gevent.sleep(0) # 模拟耗时操作
print("test11") def test2():
print("test2")
gevent.sleep(0) # 模拟耗时操作
print("test22") # g1 = gevent.spawn(test1) # 将函数封装成协程,并启动
# g2 = gevent.spawn(test2)
# gevent.joinall([g1, g2]) """
# joinall() 阻塞当前流程,执行给定的greenlet(列表中的对象),等待程序执行完
# spawn是启动协程,参数为函数名及其参数 运行结果:
test1
test2
test11
test22 代码执行test1,打印test1,遇到gevent.sleep(0)时切换程序,执行test2
test()执行,打印test2,执行到gevent.sleep(0)时切换程序
执行test1在gevent.sleep(0)后面的代码,直到再次遇到gevent时,切换程序
然后在test2中,继续执行gevent后的代码,直到遇到gevent时,再次切换
直到程序执行完毕 gevent的价值在于它的使用基于epoll的libev来避开阻塞;
使用基于gevent的高效协程,来切换执行
只在遇到阻塞的时候切换,没有轮询和线程开销
"""

基于gevent的并发服务器

# 基于gevent的并发服务器实现
import gevent
# 将python内置的socket换成封装了IO多路复用的socket
from gevent import monkey;monkey.patch_all()
import socket # 实例化socket
server = socket.socket()
# 绑定ip和端口
server.bind(('0.0.0.0', 8000))
# 绑定监听数量
server.listen(1000) def worker(connection):
"""
协程需要处理的事情
:param connection:
:return:
"""
while True:
recv_data = connection.recv(1024) # 等待接收数据
if recv_data:
print(recv_data)
connection.send(recv_data) # 将接收的数据原路返回
else:
connection.close() # 发送完毕断开
break while True:
conn, addr = server.accept() # 等待客户端连接,遇到阻塞切换
gevent.spawn(worker, conn) # 生成协程,并将conn作为参数传入

gevent的通信

# gevent通信
import time
import random from gevent import monkey;monkey.patch_all()
import gevent
from gevent.queue import Queue def write(q):
while True:
print("put:{}".format('text'))
q.put('text')
gevent.sleep(0) # 模拟阻塞 def read(q):
while True:
print("get:{}".format(q.get())) # get本身是阻塞 # q = Queue()
# w = gevent.spawn(write, q) # 遇到阻塞自动切换
# r = gevent.spawn(read, q)
# gevent.joinall([w, r])

并发编程--greenlet与gevent的更多相关文章

  1. python 并发编程 协程 gevent模块

    一 gevent模块 gevent应用场景: 单线程下,多个任务,io密集型程序 安装 pip3 install gevent Gevent 是一个第三方库,可以轻松通过gevent实现并发同步或异步 ...

  2. 并发编程协程(Coroutine)之Gevent

    并发编程协程之Gevent Gevent官网文档地址:http://www.gevent.org/contents.html 基本概念 我们通常所说的协程Coroutine其实是corporate r ...

  3. python 并发编程 协程 目录

    python 并发编程 协程 协程介绍 python 并发编程 协程 greenlet模块 python 并发编程 协程 gevent模块 python 并发编程 基于gevent模块实现并发的套接字 ...

  4. 14 并发编程-(协程)-greenlet模块&gevent模块

    1.实现多个任务之间进行切换,yield.greenlet都没有实现检测I/O,greenlet在实现多任务切换下更简单 from greenlet import greenlet def eat(n ...

  5. Python进阶----异步同步,阻塞非阻塞,线程池(进程池)的异步+回调机制实行并发, 线程队列(Queue, LifoQueue,PriorityQueue), 事件Event,线程的三个状态(就绪,挂起,运行) ,***协程概念,yield模拟并发(有缺陷),Greenlet模块(手动切换),Gevent(协程并发)

    Python进阶----异步同步,阻塞非阻塞,线程池(进程池)的异步+回调机制实行并发, 线程队列(Queue, LifoQueue,PriorityQueue), 事件Event,线程的三个状态(就 ...

  6. Python自动化之select、greenlet和gevent和事件驱动模型初探

    进程.线程和协程的区别 进程拥有自己独立的堆和栈,既不共享堆,亦不共享栈,进程由操作系统调度. 线程拥有自己独立的栈和共享的堆,共享堆,不共享栈,线程亦由操作系统调度(标准线程是的). 协程和线程一样 ...

  7. python系列之 - 并发编程(进程池,线程池,协程)

    需要注意一下不能无限的开进程,不能无限的开线程最常用的就是开进程池,开线程池.其中回调函数非常重要回调函数其实可以作为一种编程思想,谁好了谁就去掉 只要你用并发,就会有锁的问题,但是你不能一直去自己加 ...

  8. day22-多并发编程基础(三)

    今天学习了并发编程中的最后一部分,协程,也是python中区别于java,c等语言中很大不同的一部分 1.协程产生的背景 2.协程的概念 3.yield模拟协程 4.协程中主要的俩个模块 5.协程的应 ...

  9. 使用Python进行并发编程

    让计算机程序并发的运行是一个经常被讨论的话题,今天我想讨论一下Python下的各种并发方式. 并发方式 线程(Thread) 多线程几乎是每一个程序猿在使用每一种语言时都会首先想到用于解决并发的工具( ...

随机推荐

  1. JavaScript随机生成布尔值

    //方法一 var rand = Boolean(Math.round(Math.random())); conosole.log(rand) // 方法二: var arr = [true,fals ...

  2. ios发送短信验证码计时器的swift实现

    转载自:http://www.jianshu.com/p/024dd2d6e6e6# Update: Xcode 8.2.1 Swift 3 先介绍一下 属性观测器(Property Observer ...

  3. 汇编窥探Swift String的底层

    String(字符串),是所有编程语言中非常重要的成员,因此非常值得去深入研究.众所周知,字符串的本质是字符序列,由若干个字符组成.比如字符串 "iOS" 由 'i'.'O'.'S ...

  4. (IDEA) 搭建Maven并使用Maven打包部署

    1.配置Maven的环境变量 a.首先我们去maven官网下载Maven程序,解压到安装目录,如图所示: b.配置M2_HOME的环境变量,然后将该变量添加到Path中 备注:必须要有JAVA_HOM ...

  5. winform 数据库资料导出Excel方法(适用于资料数据较多加载慢,不用呈现至DatagridView)

    Private Sub savefile(ByVal dgv2 As DataTable) Dim app As Object = CreateObject("Excel.Applicati ...

  6. 学习笔记01HTML

    1.五大浏览器:IE,FireFox,Chrome,Opera,Safari(Apple)所有浏览器都是这五大浏览器中作为核心引擎的.Trident(引擎):就是IE浏览器的WebBrowser控制. ...

  7. 修改tomcat默认使用的jdk版本

    1.windows平台 在csetclasspath.bat文件开头加上如下两句(指定JDK): set JAVA_HOME=C:\Program Files\Java\jdk1.7.0_79  se ...

  8. [考试反思]1024csp-s模拟测试85:以为

    愈发垃圾. T1基本全场切(除了RP<-inf的zkt和把人擦) 然后T2想了半天逐渐趋近于正解,但是因为数据有问题锅了25分,没什么好说的.T3连题意转化都没有完成.括号匹配转为+1/-1做法 ...

  9. 测试面试题集-测试用例设计:登录、购物车、QQ收藏表情、转账、充值、提现

    以下内容首发于微信公众号[ITester软件测试小栈]: 测试面试题集-2.测试用例设计 大家好 我是coco小锦鲤 上周五给大家分享了测试基础理论题 这个周五给大家分享测试用例设计题 测试用例的考察 ...

  10. python协程总结

    概述 python多线程中因为有GIL(Global Interpreter Lock 全局解释器锁 )的存在,所以对CPU密集型程序显得很鸡肋:但对IO密集型的程序,GIL会在调用IO操作前释放,所 ...