greenlet
- 安装
pip3 install greenlet
2.示例代码
from greenlet import greenlet
import time
def task1():
while True:
print("----1----")
gr2.switch()
time.sleep(1)
def task2():
while True:
print("----2-----")
gr1.switch()
time.sleep(1)
gr1 = greenlet(task1)
gr2 = greenlet(task2)
gr1.switch()
上述代码和yeild实现‘多任务’差不多(见Python-高级:生成器3(案例:使用yield完成“多任务”)) ,本质都是一个线程来回切的‘多任务’。
(实质:greenlet就是对yeild的一个封装)
gevent(利用协程的思想实现多任务)
greenlet已经实现了协程,但是还是太麻烦,gevent更强大。
原理:当一个greenlet遇到IO(input、output:输入输出,网络、文件操作)时,就自动切换到其他的greenlet,等到IO操作完成,再再适当的时候切回来执行。
由于IO操作非常耗时,经常使程序处于等待的状态,有了gevent为我们自动切换协程,就保证总有greenlet在运行,而不是等待IO。
- 安装: pip3 install gevent
- 使用:
- 示例代码:
import gevent
import time
def f(n):
for i in range(n):
print(gevent.getcurrent(), i)
# time.sleep(1) #这种方式造成的延时在gevent中不会切换
gevent.sleep(1)
# gevent遇到延伸(注!此处的延时需要用gevent.sleep())就切换
# gevent(func, args)
# 创建的时候并不执行
g1 = gevent.spawn(f, 5)
g2 = gevent.spawn(f, 5)
g3 = gevent.spawn(f, 5)
g1.join()
g2.join()
g3.join()
展示:
小结:进程切换消耗做大;协程最小,协程就类似于调用函数,一个函数在等待时,切换到另个一函数。
补充:如果代码里有很多time.sleep(),然后引入了协程,一个一个改显然不现实,此时就可以用以下方式。
from gevent import monkey
monkey.patch_all()
原理:就是检查代码中的耗时操作并将其改为gevent中可以切换的耗时。
简化的示例代码:
import gevent
import time
from gevent import monkey
monkey.patch_all()
def f(n):
for i in range(n):
print(gevent.getcurrent(), i)
time.sleep(1)
# # gevent遇到延伸(注!此处的延时需要用gevent.sleep())就切换
# # gevent(func, args)
# # 创建的时候并不执行
# g1 = gevent.spawn(f, 5)
# g2 = gevent.spawn(f, 5)
# g3 = gevent.spawn(f, 5)
# 简化写了很多join的方式
gevent.joinall([
gevent.spawn(f, 5),
gevent.spawn(f, 5),
gevent.spawn(f, 5)
])