python 协程库gevent学习--gevent数据结构及实战(三)
gevent学习系列第三章,前面两章分析了大量常用几个函数的源码以及实现原理。这一章重点偏向实战了,按照官方给出的gevent学习指南,我将依次分析官方给出的7个数据结构。以及给出几个相应使用他们的例子。
1.事件:
事件是一个可以让我们在Greenlet之间异步通信的形式贴上一个gevent指南上面的例子:
import gevent
from gevent.event import Event '''
Illustrates the use of events
''' evt = Event() def setter():
'''After 3 seconds, wake all threads waiting on the value of evt'''
print('A: Hey wait for me, I have to do something')
gevent.sleep(3)
print("Ok, I'm done")
evt.set() def waiter():
'''After 3 seconds the get call will unblock'''
print("I'll wait for you")
evt.wait() # blocking
print("It's about time") def main():
gevent.joinall([
gevent.spawn(setter),
gevent.spawn(waiter),
gevent.spawn(waiter),
]) if __name__ == '__main__': main()
这里setter和waiter一共起了三个协程。分析一下运行顺序应该很容易了解evt是干嘛的:
首先回调之行到运行setter 打印str然后gevent.sleep(3)。
然后执行第二个回调waitter()执行到evt.wait()的时候阻塞住然后切换,怎么切换的细节要分析的话又是一大波。总之就是切换了
然后执行第三个回调waitter()执行到evt.wait()又被阻塞了,这个时候继续执行下一个回调就会回到setter里面,因为没有人在他前面往hub.loop里注册了
然后这里执行"ok, i'm done" ok我撸完了,运行evt.set()将flag设置为True.
然后另外两个被阻塞的waitter的evt.wait()方法在看到flag已经为True之后不再继续阻塞运行并且结束。
可以看到,Event可以协同好几个Greenlet同时工作,并且一个主Greenlet在操作的时候可以让其他几个都处于等待的状态,可以实现一些特定的环境和需求。
import gevent
from gevent.event import AsyncResult
a = AsyncResult() def setter():
"""
After 3 seconds set the result of a.
"""
gevent.sleep(3)
a.set('Hello!') def waiter():
"""
After 3 seconds the get call will unblock after the setter
puts a value into the AsyncResult.
"""
print(a.get()) gevent.joinall([
gevent.spawn(setter),
gevent.spawn(waiter),
])
Event还有一个扩展AsyncResult, 这个扩展可以在set的时候带上数据传递给各waiter去get。这里get还是会阻塞,但是等待的就是不flag了,而是一个值或一个报错相关更详细的api或更多功能可以参考文档http://www.gevent.org/gevent.event.html。
2: 队列:
队列是一个排序的数据集合,它有常见的put / get操作, 但是它是以在Greenlet之间可以安全操作的方式来实现的。
举例来说,如果一个Greenlet从队列中取出一项,此项就不会被同时执行的其它Greenlet再取到了。可以理解成基于greenlet之间的安全队列吧还是先贴上一个官方的例子:
import gevent
from gevent.queue import Queue tasks = Queue() def worker(n):
while not tasks.empty():
task = tasks.get()
print('Worker %s got task %s' % (n, task))
gevent.sleep(0) print('Quitting time!') def boss():
for i in xrange(1,25):
tasks.put_nowait(i) gevent.spawn(boss).join() gevent.joinall([
gevent.spawn(worker, 'steve'),
gevent.spawn(worker, 'john'),
gevent.spawn(worker, 'nancy'),
])
首先初始化一个Queue()实例。这里会先运行boss() 调用put_nowait()方法不阻塞的往队列里面放24个元素。然后下面依次从Queue里对数字进行消费,起了三个协程分别命名了不同的名字,使用get方法依次消费队列里面的数字直到消费完毕。
put和get操作都有非阻塞的版本,put_nowait和get_nowait不会阻塞, 然而在操作不能完成时抛出gevent.queue.Empty或gevent.queue.Full异常。同时Queue队列可以支持设置最大队列值,查看队列现在元素数量qsize(),队列是否为空empty(),队列是否满了full()等api在使用的时候最好也参考一下文档:http://www.gevent.org/gevent.queue.html
3.Group/Pool gevent文档翻译为组合池:
组(group)是一个运行中greenlet的集合,集合中的greenlet像一个组一样 会被共同管理和调度。 它也兼饰了像Python的multiprocessing库那样的 平行调度器的角色。
我的理解是,在一个组(group)里面的greenlet会被统一管理和调度。
先看指南上的例子:
import gevent
from gevent.pool import Group def talk(msg):
for i in xrange(3):
print(msg) g1 = gevent.spawn(talk, 'bar')
g2 = gevent.spawn(talk, 'foo') group = Group()
group.add(g1)
group.add(g2)
group.join()
这个例子非常简单。就是spawn了好几个talk,然后都加到组里面。最后使用group.join()来等待所有spawn完成,每完成一个就会从group里面去掉。由于没有返回值等问题,这个demo非常简单,来看下一个稍微复杂一点的我这里把这个例子分成三个分析.
第一个例子Group().map():
from gevent import getcurrent
from gevent.pool import Group group = Group() def hello_from(n):
print('Size of group %s' % len(group))
print('Hello from Greenlet %s' % id(getcurrent()))
return n x = group.map(hello_from, xrange(3))
print type(x)
print x
这里使用了group.map()这个函数来取得各spawn的返回值。map()是由第二个参数控制迭代次数,并且传递给第一个参数值而运行的。拿这个函数举例,这里会返回一个list构成这个list的对象就是将迭代的参数传进函数运行之后的返回值。这里得到的结果是[0, 1, 2]
第二个例子Group().imap():
import gevent
from gevent.pool import Group def intensive(n):
gevent.sleep(3 - n)
return 'task', n print('Ordered')
ogroup = Group()
x = ogroup.imap(intensive, xrange(3))
print x for x in ogroup.imap(intensive, xrange(3)):
print x
这里imap与map不一样的地方可能熟悉python基础库的同学很容易看出来,map返回list对象,而imap返回一个iterable对象。所以如果要取得里面的值比如想打印就必须写成像代码最后一行那种。(或者直接包一个list让他变成map函数
python 协程库gevent学习--gevent数据结构及实战(三)的更多相关文章
- python协程详解,gevent asyncio
python协程详解,gevent asyncio 新建模板小书匠 #协程的概念 #模块操作协程 # gevent 扩展模块 # asyncio 内置模块 # 基础的语法 1.生成器实现切换 [1] ...
- python 协程库gevent学习--gevent数据结构及实战(四)
一不留神已经到第四部分了,这一部分继续总结数据结构和常用的gevent类,废话不多说继续. 1.Timeout错误类 晚上在调试调用第三方接口的时候,发现有些接口耗时非常多,觉得应该有个超时接口来限制 ...
- python 协程库gevent学习--源码学习(一)
总算还是要来梳理一下这几天深入研究之后学习到的东西了. 这几天一直在看以前跟jd对接的项目写的那个gevent代码.为了查错,基本上深入浅出了一次gevent几个重要部件的实现和其工作的原理. 这里用 ...
- python 协程库gevent学习--gevent源码学习(二)
在进行gevent源码学习一分析之后,我还对两个比较核心的问题抱有疑问: 1. gevent.Greenlet.join()以及他的list版本joinall()的原理和使用. 2. 关于在使用mon ...
- python中的协程:greenlet和gevent
python中的协程:greenlet和gevent 协程是一中多任务实现方式,它不需要多个进程或线程就可以实现多任务. 1.通过yield实现协程: 代码: import time def A(): ...
- Python协程与Go协程的区别二
写在前面 世界是复杂的,每一种思想都是为了解决某些现实问题而简化成的模型,想解决就得先面对,面对就需要选择角度,角度决定了模型的质量, 喜欢此UP主汤质看本质的哲学科普,其中简洁又不失细节的介绍了人类 ...
- Python协程与JavaScript协程的对比
前言 以前没怎么接触前端对JavaScript 的异步操作不了解,现在有了点了解一查,发现 python 和 JavaScript 的协程发展史简直就是一毛一样! 这里大致做下横向对比和总结,便于对这 ...
- Python协程(真才实学,想学的进来)
真正有知识的人的成长过程,就像麦穗的成长过程:麦穗空的时候,麦子长得很快,麦穗骄傲地高高昂起,但是,麦穗成熟饱满时,它们开始谦虚,垂下麦芒. --蒙田<蒙田随笔全集> *** 上篇论述了关 ...
- 5分钟完全掌握Python协程
本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,如有问题请及时联系我们以作处理 1. 协程相关的概念 1.1 进程和线程 进程(Process)是应用程序启动的实例,拥有代码.数据 ...
随机推荐
- nat表使用
Net Address Translation 网络地址转换 IP地址 私网IP:nat技术将私网IP转换公网IP 公网IP: iptables nat表:三条链 主要用PREROUTING,POST ...
- python3 练习题(购物车)
'''购物车程序需求:1.启动程序后,让用户输入工资,然后打印商品列表2.允许用户根据商品编号购买商品3.用户选择商品后,检查余额是否够,够就直接扣款,不够就提醒4.用户可一直购买商品,也可随时退出, ...
- Matlab计算的FFT与通过Origin计算的FFT
实验的过程中,经常需要对所采集的数据进行频谱分析,软件的选择对计算速度影响挺大的.我在实验过程中,通常使用Origin7.5来进行快速傅里叶变换,因为方便快捷,计算之后,绘出来的图也容易编辑.但是当数 ...
- 避免for循环
http://www.360doc.com/content/10/0610/22/1217721_32411251.shtml 避免使用for循环: 在Matlab中,for循环运算效率非常低,因为M ...
- https安全协议原理
那么什么是HTTPS? HTTPS(Hypertext Transfer Protocol Secure)是一种通过计算机网络进行安全通信的传输协议.HTTPS经由HTTP进行通信,但利用TLS来加密 ...
- 【Codeforces 331D3】Escaping on Beaveractor
题意:给\(b\times b\)的网格,其中有\(n\)个不交叉的箭头. 现在有\(q\)个询问,每个询问包含一个点\((x,y)\),以及一个方向\(dir\).时间\(t\). 要求从\((x, ...
- ubuntu 环境下的QT程序打包
很多的时候 需要将自己写的QT 程序发布一下 所以今天教一下 怎么在ubuntu 环境下将自己的写的Qt 程序打包打包是为了不依赖 开发环境 和开发的库. 1. QtCreate使用Release版 ...
- wifidog源码分析 - 认证服务器心跳检测线程
引言 但wifidog启动时,会自动启动认证服务器心跳检测线程,此线程默认每隔60s与认证服务器交互一次,会将路由器的信息(系统启动时长,内存使用情况和系统平均负载)告知认证服务器,并通过一个&quo ...
- Python文学家为Python写的一首词?(附中英文版)
The Zen of Python, by Tim Peters (Python之禅 by Tim Peters) Beautiful is better than ugly. (优美胜于丑陋(Pyt ...
- C# 中堆与栈的浅记
C# 中堆与栈的浅记 什么是堆和栈? 简言之.堆和栈是驻留在内存中的区域,它们的作用是帮助我们运行代码.在.Net Framework 环境下,当我们的代码运行时,内存中的堆和栈便存储了这些代码,并包 ...