10-协程:gevent
目标¶
- 知道使用 gevent 可以实现协程
greenlet已经实现了协程,但是这个还的人工切换,是不是觉得太麻烦了,不要捉急,python还有一个比greenlet更强大的并且能够自动切换任务的第三方库gevent
其原理是当一个greenlet遇到IO(指的是input output 输入输出,比如网络、文件操作等)操作时,比如访问网络,就自动切换到其他的greenlet,等到IO操作完成,再在适当的时候切换回来继续执行。
由于IO操作非常耗时,经常使程序处于等待状态,有了gevent为我们自动切换协程,就保证总有greenlet在运行,而不是等待IO
安装¶
sudo pip3 install gevent
也在pycharm中配置可用资源
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)
运行结果
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(猴子),所以猴子补丁的叫法是这么莫名其妙的得来的。
猴子补丁主要有以下几个用处:
- 在运行时替换方法、属性等
- 在不修改第三方代码的情况下增加原来不支持的功能
- 在运行时为内存中的对象增加patch而不是在磁盘的源代码中增加
# 打补丁,让gevent识别自己提供或者网络请求的耗时操作
from gevent import monkey
monkey.patch_all()
运行结果
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()
查看当前执行任务的协程名称