10-协程:gevent

目标

  • 知道使用 gevent 可以实现协程

greenlet已经实现了协程,但是这个还的人工切换,是不是觉得太麻烦了,不要捉急,python还有一个比greenlet更强大的并且能够自动切换任务的第三方库gevent

其原理是当一个greenlet遇到IO(指的是input output 输入输出,比如网络、文件操作等)操作时,比如访问网络,就自动切换到其他的greenlet,等到IO操作完成,再在适当的时候切换回来继续执行。

由于IO操作非常耗时,经常使程序处于等待状态,有了gevent为我们自动切换协程,就保证总有greenlet在运行,而不是等待IO

安装

sudo pip3 install gevent

image-20180704233640611

也在pycharm中配置可用资源

image-20180618134527108

1. gevent的使用

import time
import gevent


def work1():
    for i in range(5):
        print("work1 -----1")
        time.sleep(0.5)


def work2():
    for i in range(5):
        print("work2 -----2")
        time.sleep(0.5)


# 创建携程并指派任务
g1 = gevent.spawn(work1)
g2 = gevent.spawn(work2)

# 等待协程执行完成再关闭主线程
g1.join()
g2.join()

运行结果

work1 -----1
work1 -----1
work1 -----1
work1 -----1
work1 -----1
work2 -----2
work2 -----2
work2 -----2
work2 -----2
work2 -----2

我们是希望 gevent 帮我们我们自动切换协程以达到work1 和 work2 交替执行的目的,但并没有达到我们的效果

原因是因为 time.sleep(0.2) 并没有被正确的识别到,所以要使用下面的 gvent.sleep() 来实现延时(耗时)操作

2. gevent.sleep()

        # 使用gevent.sleep() 使得延时操作能够被gevent识别
        gevent.sleep(0.5)

image-20180618142715640

运行结果

work1 -----1
work2 -----2
work1 -----1
work2 -----2
work1 -----1
work2 -----2
work1 -----1
work2 -----2
work1 -----1
work2 -----2

Process finished with exit code 0

发现worK1和work2 能够交替执行,我们使用协程的目标就达到了!

但是问题是,如果我们以前的代码中大量使用了time.sleep()等耗时方法,如果全部改为gevent.sleep()

为了让程序更好的兼容time.sleep()我们可以给程序打补丁,以实现兼容

3. 给程序打补丁(猴子补丁)

关于猴子补丁为啥叫猴子补丁,据说是这样子的:

这个叫法起源于Zope框架,大家在修正Zope的Bug的时候经常在程序后面追加更新部分,这些被称作是“杂牌军补丁(guerilla patch)”,后来guerilla就渐渐的写成了gorllia((猩猩),再后来就写了monkey(猴子),所以猴子补丁的叫法是这么莫名其妙的得来的。

猴子补丁主要有以下几个用处:

  1. 在运行时替换方法、属性等
  2. 在不修改第三方代码的情况下增加原来不支持的功能
  3. 在运行时为内存中的对象增加patch而不是在磁盘的源代码中增加
# 打补丁,让gevent识别自己提供或者网络请求的耗时操作
from gevent import monkey
monkey.patch_all()

运行结果

image-20180618143123868

work1 -----1
work2 -----2
work1 -----1
work2 -----2
work1 -----1
work2 -----2
work1 -----1
work2 -----2
work1 -----1
work2 -----2

Process finished with exit code 0

4.查看当前执行任务的协程

gevent.getcurrent()

查看当前执行任务的协程名称

image-20180618161426870