并发编程--greenlet与gevent
什么是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的更多相关文章
- python 并发编程 协程 gevent模块
一 gevent模块 gevent应用场景: 单线程下,多个任务,io密集型程序 安装 pip3 install gevent Gevent 是一个第三方库,可以轻松通过gevent实现并发同步或异步 ...
- 并发编程协程(Coroutine)之Gevent
并发编程协程之Gevent Gevent官网文档地址:http://www.gevent.org/contents.html 基本概念 我们通常所说的协程Coroutine其实是corporate r ...
- python 并发编程 协程 目录
python 并发编程 协程 协程介绍 python 并发编程 协程 greenlet模块 python 并发编程 协程 gevent模块 python 并发编程 基于gevent模块实现并发的套接字 ...
- 14 并发编程-(协程)-greenlet模块&gevent模块
1.实现多个任务之间进行切换,yield.greenlet都没有实现检测I/O,greenlet在实现多任务切换下更简单 from greenlet import greenlet def eat(n ...
- Python进阶----异步同步,阻塞非阻塞,线程池(进程池)的异步+回调机制实行并发, 线程队列(Queue, LifoQueue,PriorityQueue), 事件Event,线程的三个状态(就绪,挂起,运行) ,***协程概念,yield模拟并发(有缺陷),Greenlet模块(手动切换),Gevent(协程并发)
Python进阶----异步同步,阻塞非阻塞,线程池(进程池)的异步+回调机制实行并发, 线程队列(Queue, LifoQueue,PriorityQueue), 事件Event,线程的三个状态(就 ...
- Python自动化之select、greenlet和gevent和事件驱动模型初探
进程.线程和协程的区别 进程拥有自己独立的堆和栈,既不共享堆,亦不共享栈,进程由操作系统调度. 线程拥有自己独立的栈和共享的堆,共享堆,不共享栈,线程亦由操作系统调度(标准线程是的). 协程和线程一样 ...
- python系列之 - 并发编程(进程池,线程池,协程)
需要注意一下不能无限的开进程,不能无限的开线程最常用的就是开进程池,开线程池.其中回调函数非常重要回调函数其实可以作为一种编程思想,谁好了谁就去掉 只要你用并发,就会有锁的问题,但是你不能一直去自己加 ...
- day22-多并发编程基础(三)
今天学习了并发编程中的最后一部分,协程,也是python中区别于java,c等语言中很大不同的一部分 1.协程产生的背景 2.协程的概念 3.yield模拟协程 4.协程中主要的俩个模块 5.协程的应 ...
- 使用Python进行并发编程
让计算机程序并发的运行是一个经常被讨论的话题,今天我想讨论一下Python下的各种并发方式. 并发方式 线程(Thread) 多线程几乎是每一个程序猿在使用每一种语言时都会首先想到用于解决并发的工具( ...
随机推荐
- Java基础(六)判断两个对象相等:equals、hashcode、toString方法
1.equal方法 Object类中的equal方法用于检测一个对象是否等于另外一个对象.在Object类中,这个方法将判断两个对象是否具有相同的引用.如果两个对象具有相同的引用,它们一定是相等的.然 ...
- NetworkManager网络通讯_破产版NetworkManager(五)
根据对NetWorkServer 以及NetworkClient的理解,编写一个简易版的NetWork Manager.惯例全部代码放在最后 (一)NetWorkServer与NetworkClien ...
- Computer English Notes
Chapter 1 : About Computer Answer the following - Abbreviation LBS - Location-Based Services HTML - ...
- kali linux 开启配置ssh服务
1. 一.配置SSH参数 修改sshd_config文件,命令为: vi /etc/ssh/sshd_config 将#PasswordAuthentication no的注释去掉,并且将NO修 ...
- forEach,map,every,some,filter简单用法实例
平时简单总结:不足之处还望见谅: 实例: 11.1 forEach:只能进行取值操作,不能进行修改 arr.forEach(function(element,index,arr){});//注意参数: ...
- xss代码集
</script>"><script>prompt(1)</script> </ScRiPt>"><ScRiPt& ...
- numpy.array 合并和分割
# 导包 import numpy as np numpy.array 的合并 .concatenate() 一维数组 x = np.array([1, 2, 3]) # array([1, 2, 3 ...
- CSPS 模拟 70
考试结束看A了两题就有点遗憾开开心心地去颓废了 吐槽一下这局LRS开的有点睿智,SD当的有点累 T1跟前边一个T1挺像,打表也可以 T2智障dp,开滚动数组就不会被卡空间了 T3牛逼构造题,虽然不是很 ...
- Python基本数据结构之集合
一道python面试的一个小问题,说怎么使用一行代码将一个列表里的重复元素,其实这里只要将列表转换成集合就可以了. 定义 集合跟我们学的列表有点像,也是可以存一堆数据,不过它有几个独特的特点,令其在整 ...
- m101 真*sb($\huge 全场最瞎$)
不想说这场考试,T1全场切,但是我: T3全场30,但是: 鬼知道我为什么敲的是p*p啊(而且还炸精了!) kuku----! $\huge 全场最瞎$