python协程初步--gevent库使用以及解释什么是猴子补丁monkey_patch


协程工作的特点是遇到阻塞或耗时的任务时就切换,协程的生存依赖于线程,线程依赖于进程

  • 一个似乎有点问题的例子
import gevent,time

def kisscpc(num):
    for i in range(num):
        print ("吻了第%s下陈培昌"%(i+1),gevent.getcurrent())
    time.sleep(1)

def kisscj(num):
    for i in range(num):
        print ("吻了第%s下程劲"%(i+1),gevent.getcurrent())
    time.sleep(1)

def kissxxd(num):
    for i in range(num):
        print ("吻了第%s下徐晓冬"%(i+1),gevent.getcurrent())
    time.sleep(1)

g1 = gevent.spawn(kisscj,3)
g2 = gevent.spawn(kisscpc,2)
g3 = gevent.spawn(kissxxd,5)
g1.join()
g2.join()
g3.join()

输出结果:

吻了第1下程劲 <Greenlet at 0x7fe77eed7648: kisscj(3)>
吻了第2下程劲 <Greenlet at 0x7fe77eed7648: kisscj(3)>
吻了第3下程劲 <Greenlet at 0x7fe77eed7648: kisscj(3)>
吻了第1下陈培昌 <Greenlet at 0x7fe77eed7a48: kisscpc(2)>
吻了第2下陈培昌 <Greenlet at 0x7fe77eed7a48: kisscpc(2)>
吻了第1下徐晓冬 <Greenlet at 0x7fe77eed7b48: kissxxd(5)>
吻了第2下徐晓冬 <Greenlet at 0x7fe77eed7b48: kissxxd(5)>
吻了第3下徐晓冬 <Greenlet at 0x7fe77eed7b48: kissxxd(5)>
吻了第4下徐晓冬 <Greenlet at 0x7fe77eed7b48: kissxxd(5)>
吻了第5下徐晓冬 <Greenlet at 0x7fe77eed7b48: kissxxd(5)>

貌似这样的结果并未能达到我们所期待的并发效果,任务仍旧是按部就班的执行。答案在于使用gevent时,相关的一切都要更换成gevent的

  • 耗时,阻塞部分换成gevent库的实现
import gevent,time def kisscpc(num): for i in range(num): print ("吻了第%s下陈培昌"%(i+1),gevent.getcurrent()) #time.sleep(1) gevent.sleep(1) def kisscj(num): for i in range(num): print ("吻了第%s下程劲"%(i+1),gevent.getcurrent()) #time.sleep(1) gevent.sleep(1) def kissxxd(num): for i in range(num): print ("吻了第%s下徐晓冬"%(i+1),gevent.getcurrent())    #time.sleep(1) gevent.sleep(1) g1 = gevent.spawn(kisscj,3) g2 = gevent.spawn(kisscpc,2) g3 = gevent.spawn(kissxxd,5) g1.join() g2.join() g3.join()

输出结果:

吻了第1下程劲 <Greenlet at 0x7f2af804e648: kisscj(3)>
吻了第1下陈培昌 <Greenlet at 0x7f2af804ea48: kisscpc(2)>
吻了第1下徐晓冬 <Greenlet at 0x7f2af804eb48: kissxxd(5)>
吻了第2下程劲 <Greenlet at 0x7f2af804e648: kisscj(3)>
吻了第2下陈培昌 <Greenlet at 0x7f2af804ea48: kisscpc(2)>
吻了第2下徐晓冬 <Greenlet at 0x7f2af804eb48: kissxxd(5)>
吻了第3下程劲 <Greenlet at 0x7f2af804e648: kisscj(3)>
吻了第3下徐晓冬 <Greenlet at 0x7f2af804eb48: kissxxd(5)>
吻了第4下徐晓冬 <Greenlet at 0x7f2af804eb48: kissxxd(5)>
吻了第5下徐晓冬 <Greenlet at 0x7f2af804eb48: kissxxd(5)>

哟比~这才是我们期盼的!

但是,对于一些早期的代码,每个任务的耗时部分仍有可能采用了常规的代码写法(而不是gevent.方法名),这就意味着,我们需要改动代码的绝大多数部分

这时,猴子补丁就派上用场了

import gevent,time from gevent import monkey monkey.patch_all() def kisscpc(num): for i in range(num): print ("吻了第%s下陈培昌"%(i+1),gevent.getcurrent()) time.sleep(1) #gevent.sleep(1) def kisscj(num): for i in range(num): print ("吻了第%s下程劲"%(i+1),gevent.getcurrent()) time.sleep(1) #gevent.sleep(1) def kissxxd(num): for i in range(num): print ("吻了第%s下徐晓冬"%(i+1),gevent.getcurrent()) time.sleep(1) #gevent.sleep(1) g1 = gevent.spawn(kisscj,3) g2 = gevent.spawn(kisscpc,2) g3 = gevent.spawn(kissxxd,5) g1.join() g2.join() g3.join()

输出结果:

吻了第1下程劲 <Greenlet at 0x7f97e4981948: kisscj(3)>
吻了第1下陈培昌 <Greenlet at 0x7f97e4981a48: kisscpc(2)>
吻了第1下徐晓冬 <Greenlet at 0x7f97e4981b48: kissxxd(5)>
吻了第2下程劲 <Greenlet at 0x7f97e4981948: kisscj(3)>
吻了第2下陈培昌 <Greenlet at 0x7f97e4981a48: kisscpc(2)>
吻了第2下徐晓冬 <Greenlet at 0x7f97e4981b48: kissxxd(5)>
吻了第3下程劲 <Greenlet at 0x7f97e4981948: kisscj(3)>
吻了第3下徐晓冬 <Greenlet at 0x7f97e4981b48: kissxxd(5)>
吻了第4下徐晓冬 <Greenlet at 0x7f97e4981b48: kissxxd(5)>
吻了第5下徐晓冬 <Greenlet at 0x7f97e4981b48: kissxxd(5)>

我们看到仅仅用了monkey.patch_all()就达到了期待的效果,而其他方面几乎没什么改变

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM