协程模块gevent

更新:导入一个有monkey.patch_all()的库,应该用函数把它包起来,否则会抛出错误python

- RuntimeError: cannot release un-acquired lock 编程

 

在《python高性能编程》一书中做者开始讲协程用的就是gevent模块做为例子。先举一个简单的例子:函数

协程极大大提升了性能

若是有100个foo,bar函数,每一个须要阻塞一秒,那么串行执行须要100秒以上,而I/O多路复用执行,在一秒以后100个程序执行完毕。性能

协程提升性能的缘由ui

  - 全部的阻塞请求同时发生,只要函数输入到位
    -  cpu和操做系统的高度配合
spa

    -能够这么想象   操作系统

     1  线程读代码,读到一步须要去取数据,
     2  线程本身不取数据,叫操做系统去取,取数据步骤参考途中1,3,4,2
     3  操做系统取数据,线程就不读代码了,不干其余事,就在这等着
     4 等数据到了,线程继续读代码,按代码干事
线程

 -重点来了,IO多路复用以后事情发生了变化:协程

   - 线程很快找到查看了代码,发现代码中指出了有一些代码是能够同时执行的
   - 好比下图有4处能够同时执行的代码,
对象

    -每一处代码里面可能也有阻塞,因为更里面的阻塞还不能发起请求主要先不关注,

    - 线程拿起1处的代码,向系统发起请求,不等待,回到代码2处

    - 再去操做系统处发送请求,如此反复,直到代码代表的特殊代码块都发起了请求
   - 线程毫无停歇,只要操做系统使其获得数据,他就运行代码,并重复以上步骤 
   - 对比:在串行的状况下,线程在1.1处停下等待0.1s,而IO多路复用已经把活全作完了

 


协程做用的范围:
 -   如下两个条件同时具有

         I/O密集型任务。
               任务自己结果不受其余任务
 

如何标记特殊代码块。(猴子补丁+gevent.spawn())

  - 打上猴子补丁

    from gevent import monkey
    monkey.patch_all()

  - gevent.spawn(function,*arg,**kwargs) 

    若是一个function内部没有阻塞,那么到这一步,正常执行
    若是function能有阻塞,那么它被冻结并被标记成特殊代码块
  - 使用内置方法使其开始执行

    gevent.joinall()生成对象是list类型

         iwait生成对象是生成器类型

    对单个对象使用.join()方法,可是没法经过.value获取函数返回值

    对单个对象使用.get()方法,能够直接运行并得到返回值,get(timeout=3)还能设置超时时间
        - 无论哪一个方法,生成对象的元素使用.value,获得那些特殊代码块的返回值,

    若是没有返回值,那就不用管

信号量(from gevent.lock import BoundedSemaphore)

   -  生成计算器对象,并设置值

    bigest=BoundedSemaphore(5)

      生成最大数为5的计数器

   - 在代码中调用

    使用with方法

    或使用bigest.acquire(), bigest.release()

只能用一次的超时控制(gevent.Timeout):

  - 在.join()方法前加上
     timeout=Timeout(2)

     timeout.start() 

  - timeout支持with调用,其__enter__()方法调用了start(),不知道在函数内部调用会有什么效果?

还有许多内容,但用好上面这些已能让你代码执行速度快上十倍了。

 

好吧,再来一点干货:不一样线程内相互控制以及传递值

   import gevent from gevent.event import AsyncResult

  a = AsyncResult()

  a.set('值')
  a.get()='值'

  解释:a实例化时给全部a.get() 后面的代码加锁,而后a.set()解锁,a.get()获取一个值 

相关文章
相关标签/搜索