文档章节

Gevent事件/队列/组/池/信号量/子进程

乐搏学院
 乐搏学院
发布于 2017/02/27 11:12
字数 2373
阅读 34
收藏 0
点赞 0
评论 0

常用结构:

1.Event类,事件主要用于Greenlet之间的异步通信

e = gevent.event.Event() -> Event

说明: 创建一个信号对象

e.set() -> None

说明: 设置标志位

e.clear() -> None

说明: 清除标志位

e.wait() -> None

说明: 阻塞直至标志位被设置

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

#!/usr/bin/env python

# -*- coding: utf-8 -*-

"""

#

# Authors: limanman

# OsChina: http://xmdevops.blog.51cto.com/

# Purpose:

#

"""

# 说明: 导入公共模块

import gevent

from gevent.event import Event

# 说明: 导入其它模块

def setter(e):

    print 'I'

    gevent.sleep(3)

    print 'LOVE'

    e.set()

def waiter(e):

    e.wait()

    print 'You'

if __name__ == '__main__':

    = Event()

    gevent.joinall([

        gevent.spawn(setter, e),

        gevent.spawn(waiter, e),

        gevent.spawn(waiter, e),

        gevent.spawn(waiter, e),

        gevent.spawn(waiter, e)

    ])

a = gevent.event.AsyncResult() -> AsyncResult

说明: 创建一个扩展可携带数据的信号对象

a.set(value=None) -> None

说明: 设置带数据的标志位

a.e.clear() -> None

说明: 清除带数据的标志位

a.get(block=True, timeout=None) -> obj

说明: 阻塞直至标志位被设置并返回value值,可设置timeout到点抛出Timeout异常

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

#!/usr/bin/env python

# -*- coding: utf-8 -*-

"""

#

# Authors: limanman

# OsChina: http://xmdevops.blog.51cto.com/

# Purpose:

#

"""

# 说明: 导入公共模块

import gevent

from gevent.event import AsyncResult

# 说明: 导入其它模块

def setter(a):

    print 'I'

    gevent.sleep(3)

    print 'LOVE'

    a.set('I LOVE')

def waiter(a):

    value = a.get()

    if e.successful:

        print 'found notice: recv data from setter %s.' % (value,)

    print 'You'

if __name__ == '__main__':

    = AsyncResult()

    gevent.joinall([

        gevent.spawn(setter, a),

        gevent.spawn(waiter, a),

        gevent.spawn(waiter, a),

        gevent.spawn(waiter, a),

        gevent.spawn(waiter, a)

    ])

 

2. Queue类,常用用于Greenlet之间的异步共享

q = gevent.queue.Queue(maxsize=None, items=None) -> Queue

说明: 创建一个指定大小包含指定items的队列对象

q.empty() -> Boolean

说明: 队列是否为空

q.full() -> Boolean

说明: 队列是否已满,如果初始化时maxsize为None时队列永远不会满,除非内存耗尽

q.get(block=True, timeout=None) -> obj

说明: 队列尾部弹出并返回末尾元素,block为True如果队列为空会一直等待,否则会抛出gevent.queue.Empty异常

q.get_nowait() -> obj

说明: 同q.get(block=False),如果队列为空直接返回gevent.queue.Empty

q.put(item, block=True, timeout=None) -> None

说明: 队列头部插入item,如果block为True则等待队列有空间时再插入,如果超出timeout则抛出Timeout异常,否则直接抛出gevent.queue.Full异常

q.put_nowait(self, item) -> None

说明: 同q.put(block=False),如果队列满直接返回gevent.queue.Full

q.qsize() -> int

说明: 返回队列的元素数

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

#!/usr/bin/env python

# -*- coding: utf-8 -*-

"""

#

# Authors: limanman

# OsChina: http://xmdevops.blog.51cto.com/

# Purpose:

#

"""

# 说明: 导入公共模块

import gevent

from gevent.queue import Queue

# 说明: 导入其它模块

def boss(q):

    for in xrange(25):

        q.put_nowait(_)

def work(name, q):

    while not q.empty():

        task = q.get()

        print 'found notice: worker %s got task-%s' % (name, task)

        gevent.sleep(0)

if __name__ == '__main__':

    = Queue()

    = gevent.spawn(boss, q)

    g.join()

    workers = []

    for in ('limanman''liuzhen''zhenbao'):

        workers.append(gevent.spawn(work, _, q))

    gevent.joinall(workers)

说明: 如上演示了一个老板平均分配任务给指定数目的员工的例子,为了实现每个员工都能拿到任务,我们手动的gevent.sleep(0)互相切换(关键是调用函数中没有确定性的阻塞函数)实现.

 

3. Group类,常用于不限制数量的管理异步任务的分组且可搜集运行结果

g = gevent.pool.Group(*args) -> Group

说明: 创建一个组对象,其实就是一个不限greenlets数量的pool,可以随时添加/删除/关闭greenlet对象

g.add(greenlet) -> None

说明: 向组中添加一个greenlet对象

g.discard(greenlet) -> None

说明: 从组中删除一个greenlet对象

g.join(timeout=None, raise_error=False) -> None

说明: 等待组中所有的greenlets都执行完毕再进行下一步

g.kill(exception=<class 'greenlet.GreenletExit'>, block=True, timeout=None) -> None

说明: 关闭组内所有运行中的greenlet对象

g.killone(self, greenlet, exception=<class 'greenlet.GreenletExit'>, block=True, timeout=None) -> None

说明: 关闭组内指定运行的greenlet对象

g.apply(self, func, args=None, kwds=None) -> obj

说明: 同apply单次调用func并返回运行结果

g.apply_async(self, func, args=None, kwds=None, callback=None) -> greenlet

说明: 同上但是返回的不是直接的运行结果而是异步对象greenlet,需要再次调用其.get()方法才能获取最终结果

g.imap(self, func, *iterables, **kwargs) -> IMap

g.imap_unordered(self, func, *iterables, **kwargs) -> IMapUnordered

g.map(self, func, iterable) -> list

g.map_async(self, func, iterable, callback=None) -> GreenletGroup

说明: 为了简化协程的使用,调用map/imap实现任务快速分组,基本上返回的对象都需要再次调用get()方法获取最终运行结果,经测试发现调用函数传递多个参数时通过map/imap类方法传参时有bug,已反馈GitHub.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

#!/usr/bin/env python

# -*- coding: utf-8 -*-

"""

#

# Authors: limanman

# OsChina: http://xmdevops.blog.51cto.com/

# Purpose:

#

"""

# 说明: 导入公共模块

import gevent

import itertools

from gevent.pool import Group

from gevent.queue import Queue

# 说明: 导入其它模块

def add_worker(name, q):

    while not q.empty():

        task = q.get()

        print 'found notice: worker(%s:%s) got task(%s)' % (name, gevent.getcurrent(), task)

        gevent.sleep(0)

if __name__ == '__main__':

    = Queue()

    = Group()

    # 添加任务

    for in xrange(100):

        q.put_nowait(_)

    # 通用方法

    for worker in ('langlang''fengfeng''shuishui'):

        g.add(gevent.spawn(add_worker, worker, q))

    g.join()

 

4. Pool类,常用于限制数量的管理异步任务,在受限于网络和IO的任务时候比较有优势

p =  gevent.pool.Pool(size=None, greenlet_class=None) -> Pool

说明: 创建一个协程池对象,可以指定其实协程数

p.add(greenlet) -> None

说明: 尝试向协程池中添加greenlet对象,阻塞直到有池中有协程完毕有剩余空间

p.free_count() -> int

说明: 返回池中剩余的空间,也就是可以add的greenlet数

p.full() -> boolean

说明: 返回池是否已满

p.start(greenlet) -> None

说明: 启动未启动的greenlet且将其加入pool监控

p.imap(self, func, *iterables, **kwargs) -> IMap

p.imap_unordered(self, func, *iterables, **kwargs) -> IMapUnordered

p.map(self, func, iterable) -> list

p.map_async(self, func, iterable, callback=None) -> GreenletGroup

说明: 为了简化协程的使用,调用map/imap实现任务快速分组,基本上返回的对象都需要再次调用get()方法获取最终运行结果,经测试发现调用函数传递多个参数时通过map/imap类方法传参时有bug,已反馈GitHub.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

#!/usr/bin/env python

# -*- coding: utf-8 -*-

"""

#

# Authors: limanman

# OsChina: http://xmdevops.blog.51cto.com/

# Purpose:

#

"""

# 说明: 导入公共模块

import gevent

from gevent.pool import Pool

# 说明: 导入其它模块

def pool_size(p):

    print 'found notice: current pool size: %d free %d' % (len(p), p.free_count())

if __name__ == '__main__':

    = Pool(2)

    p.map(pool_size, [p]*3)

 

5. BoundedSemaphore类,常用于限制资源同时被多少个协程访问,通过限制同时发放锁的数量来限制资源访问

b = gevent.lock.BoundedSemaphore(n) -> BoundedSemaphore

说明: 创建一个信号量对象,限制资源同时只能被n个协程访问,其实就是每次分发n把锁,只有有人释放了锁才会重新追加分发锁

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

#!/usr/bin/env python

# -*- coding: utf-8 -*-

"""

#

# Authors: limanman

# OsChina: http://xmdevops.blog.51cto.com/

# Purpose:

#

"""

# 说明: 导入公共模块

import gevent

from gevent.pool import Pool

from gevent.lock import BoundedSemaphore

# 说明: 导入其它模块

= BoundedSemaphore(2)

def work(name):

    with b:

        print 'found notice: worker %s acquire sem lock.' % (name,)

        gevent.sleep(0)

    print 'found notice: worker %s release sem lock.' % (name,)

if __name__ == '__main__':

    = Pool()

    p.map(work, ['李满满''刘珍珍''罗诗瑶'])

 

局部变量:

说明:  Gevent内部实现以greenlet的getcurrent()为键,在一个私有命名空间寻址的全局查找,使得local对象可以在不同的greenlet对象中存在且相互隔离,很多继承了gevent的web框架将HTTP会话对象以局部变量的形式存储在gevent内

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

#!/usr/bin/env python

# -*- coding: utf-8 -*-

"""

#

# Authors: limanman

# OsChina: http://xmdevops.blog.51cto.com/

# Purpose:

#

"""

# 说明: 导入公共模块

import time

import gevent

from gevent.local import local

# 说明: 导入其它模块

def session_manager(l, user):

    l.name = user

    l.timestamp = time.time()

    print 'found notice: user %s login in and online.' % (user,)

    gevent.sleep(5)

    l.name = user

    l.timestamp = time.time()

    print 'found notice: user %s session expire outs.' % (user,)

    print '''

    name: %s

    status: offline

    timestamp: %s

    ''' % (l.name, l.timestamp)

if __name__ == '__main__':

    = local()

    gevent.joinall([

        gevent.spawn(session_manager, l, '李满满'),

        gevent.spawn(session_manager, l, '刘珍珍'),

    ])

 

进程相关:

1. gevent.subprocess类,常用于作为subprocess模块增强版使用,支持异步协作式等待子进程

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

#!/usr/bin/env python

# -*- coding: utf-8 -*-

"""

#

# Authors: limanman

# OsChina: http://xmdevops.blog.51cto.com/

# Purpose:

#

"""

# 说明: 导入公共模块

import time

import gevent

from gevent.subprocess import PIPE, Popen

# 说明: 导入其它模块

def task001():

    while True:

        print time.time()

        gevent.sleep(1)

if __name__ == '__main__':

    task = gevent.spawn(task001)

    task.start()

    # 中间插入子进程

    = Popen(['ls;sleep 5'], shell=True, stdout=PIPE, stderr=PIPE)

    out, err = p.communicate()

    print out

    # 等待协程的结束

    task.join()

说明: 如上实例简单演示了支持异步协作子进程gevent.subprocess,首先task.start()启动协程调用但不会等待调用结束然后执行Popen()子进程,默认的Popen会阻塞主进程,但是在这里我们可以看到程序并没有阻塞而是继续执行task001,由于我们在最后task.join()会等待task001结束,而task001是一个死循环,所以一旦Popen子进程阻塞,立马会切换到task001执行,所以程序并不会阻塞

 

 

登录乐搏学院官网http://www.learnbo.com/

或关注我们的官方微博微信,还有更多惊喜哦~

 

 

本文出自 “满满李 - 运维开发之路” 博客,请务必保留此出处http://xmdevops.blog.51cto.com/11144840/1862487

© 著作权归作者所有

共有 人打赏支持
乐搏学院
粉丝 6
博文 526
码字总数 707467
作品 0
丰台
程序员
Python gevent学习笔记 3

在上一篇里面介绍了gevent的最主要的功能,先来来了解一下gevent里面一些更加高级的功能。 事件 事件是一种可以让greenlet进行异步通信的手段。 import geventfrom gevent.event import Asyn...

贱圣 ⋅ 2013/07/10 ⋅ 0

Python自动化开发学习10

多线程的使用场景 上次讲了由于GIL锁的存在,Python的多线程是假的,用的还是CPU的单核。Python的多线程只是利用了CPU的上下文切换,上下分切换也是占用CPU的。那么什么时候用多行程?Pytho...

骑士救兵 ⋅ 2017/12/28 ⋅ 0

Python学习记录-多进程和多线程

Python学习记录-多进程和多线程 [TOC] 1. 进程和线程 进程 狭义定义:进程是正在运行的程序的实例(an instance of a computer program that is being executed)。 广义定义:进程是一个具有...

ygqygq2 ⋅ 04/27 ⋅ 0

Python爬虫进阶六之多进程的用法

前言 在上一节中介绍了thread多线程库。python中的多线程其实并不是真正的多线程,并不能做到充分利用多核CPU资源。 如果想要充分利用,在python中大部分情况需要使用多进程,那么这个包就叫...

_周小董 ⋅ 2017/12/24 ⋅ 0

2.进程与线程

进程 进程模型 操作系统中最核心的概念是进程:这是对正在运行程序的一个抽象。 一个进程就是一个正在执行程序的实例,包括程序计数器、寄存器和变量的当前值。 在多道程序设计中,一个CPU能...

SeaRise ⋅ 2017/11/11 ⋅ 0

关于进程间通信的学习心得

进程:进程是指独立地址空间的指令序列 进程的五种状态:新建,就绪,运行,睡眠,僵死 进程间通信:是不同进程之间进行一些"接触",这种接触有简单,有复杂。机制不同,复杂度也不同。通信是...

晨曦之光 ⋅ 2012/03/09 ⋅ 0

python模块介绍-gevent介绍:基于协程的网络库

python模块介绍-gevent介绍:基于协程的网络库 介绍 gevent是基于协程的Python网络库。特点: 基于libev的快速事件循环(Linux上epoll,FreeBSD上kqueue)。 基于greenlet的轻量级执行单元。 ...

磁针石 ⋅ 2014/01/13 ⋅ 2

Python基础 - 第九天 - paramiko模块、进程、线程

本篇内容: 1.paramiko模块使用 2.进程、线程简介 3.python调用线程的方法 4.join - 等待线程执行 5.守护线程 6.GIL - 全局解释器锁 7.互斥锁 8.信号量 9.事件 10.队列 一、paramiko模块使用...

习惯_就好 ⋅ 2017/12/12 ⋅ 0

6种Linux进程间的通信方式

进程的概念 进程是操作系统的概念,每当我们执行一个程序时,对于操作系统来讲就创建了一个进程,在这个过程中,伴随着资源的分配和释放。可以认为进程是一个程序的一次执行过程。 进程通信的...

问题终结者 ⋅ 04/16 ⋅ 0

UNIX环境高级编程 第十五章:进程间通信:是指在不同进程之间传播或交换信息

IPC的方式通常有管道(包括无名管道和命名管道(FIFO))、消息队列、信号量、、共享存储、Socket、Streams等。其中 Socket和Streams支持不同主机上的两个进程IPC。 1.管道,通常指无名管道,是...

qiangzhenyi1207 ⋅ 01/16 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

mysql5.7系列修改root默认密码

操作系统为centos7 64 1、修改 /etc/my.cnf,在 [mysqld] 小节下添加一行:skip-grant-tables=1 这一行配置让 mysqld 启动时不对密码进行验证 2、重启 mysqld 服务:systemctl restart mysql...

sskill ⋅ 15分钟前 ⋅ 0

Intellij IDEA神器常用技巧六-Debug详解

在调试代码的时候,你的项目得debug模式启动,也就是点那个绿色的甲虫启动服务器,然后,就可以在代码里面断点调试啦。下面不要在意,这个快捷键具体是啥,因为,这个keymap是可以自己配置的...

Mkeeper ⋅ 19分钟前 ⋅ 0

zip压缩工具、tar打包、打包并压缩

zip 支持压缩目录 1.在/tmp/目录下创建目录(study_zip)及文件 root@yolks1 study_zip]# !treetree 11└── 2 └── 3 └── test_zip.txt2 directories, 1 file 2.yum...

蛋黄Yolks ⋅ 22分钟前 ⋅ 0

聊聊HystrixThreadPool

序 本文主要研究一下HystrixThreadPool HystrixThreadPool hystrix-core-1.5.12-sources.jar!/com/netflix/hystrix/HystrixThreadPool.java /** * ThreadPool used to executed {@link Hys......

go4it ⋅ 40分钟前 ⋅ 0

容器之上传镜像到Docker hub

Docker hub在国内可以访问,首先要创建一个账号,这个后面会用到,我是用126邮箱注册的。 1. docker login List-1 Username不能使用你注册的邮箱,要用使用注册时用的username;要输入密码 ...

汉斯-冯-拉特 ⋅ 47分钟前 ⋅ 0

SpringBoot简单使用ehcache

1,SpringBoot版本 2.0.3.RELEASE ①,pom.xml <parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.0.3.RELE......

暗中观察 ⋅ 48分钟前 ⋅ 0

监控各项服务

比如有三个服务, 为了减少故障时间,增加监控任务,使用linux的 crontab 实现. 步骤: 1,每个服务写一个ping接口 监控如下内容: 1,HouseServer 是否正常运行,所以需要增加一个ping的接口 ; http...

黄威 ⋅ 51分钟前 ⋅ 0

Spring源码解析(八)——实例创建(下)

前言 来到实例创建的最后一节,前面已经将一个实例通过不同方式(工厂方法、构造器注入、默认构造器)给创建出来了,下面我们要对创建出来的实例进行一些“加工”处理。 源码解读 回顾下之前...

MarvelCode ⋅ 51分钟前 ⋅ 0

nodejs __proto__跟prototype

前言 nodejs中完全没有class的这个概念,这点跟PHP,JAVA等面向对象的语言很不一样,没有class跟object的区分,那么nodejs是怎么样实现继承的呢? 对象 对象是由属性跟方法组成的一个东西,就...

Ai5tbb ⋅ 57分钟前 ⋅ 0

Ubuntu16.04 PHP7.0 不能用MYSQLi方式连接MySQL5.7数据库

Q: Ubuntu16.04 PHP7.0 不能用MYSQLi方式连接MySQL5.7数据库 A: 执行以下2条命令解决: apt-get install php-mysql service apache2 restart php -m 执行后会多以下4个模块: mysqli mysqlnd...

SamXIAO ⋅ 今天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部