greenlet
为了更好使用协程来完成多任务,python中greenlet模块对其封装,从而使得切换任务变得更加简单
安装方式
pip3 install greenlet
示例代码:
from greenlet import greenlet import time def test1(): while True: print("-----真-----") gr2.switch() time.sleep(0.5) def test2(): while True: print("-----真-----") gr1.switch() time.sleep(0.5) gr1 = greenlet(test1) gr2 = greenlet(test2) # 切换到gr1中运行 gr1.swith()
gevent
greenlet已经实现了协程,但是这个工人切换,是不是觉得太麻烦了,不要着急,python还有一个比greenlet更强大的并且能够自动切换任务的模块`gevent`
其原理是当一个greentlet遇到IO(指的是input ouput输入输出,比如网络、文件操作等)操作时,比如访问网络,就自动切换到其他的greenlet,等到IO完成,再适当的时候切换回来继续执行。
由于IO操作非常耗时,经常使程序处于等待状态,有了gevent我们自动切换协程,就保证总有greenlet在运行,而不是等待IO
安装
pip3 install gevent
1.gevent的使用
import gevent def f(n): for i in range(n): print(gevent.getcurrent(), i)
g1 = gevent.spawn(f, 5) g2 = gevent.spawn(f, 5) g3 = gevent.spawn(f, 5) g1.join() g2.join() g3.join()
运行结果
F:python3.6python.exe D:/pythonProjects/pynetwork/coroutine/gevent_demo.py <Greenlet "Greenlet-0" at 0x22ef10f5c48: f(5)> 0 <Greenlet "Greenlet-0" at 0x22ef10f5c48: f(5)> 1 <Greenlet "Greenlet-0" at 0x22ef10f5c48: f(5)> 2 <Greenlet "Greenlet-0" at 0x22ef10f5c48: f(5)> 3 <Greenlet "Greenlet-0" at 0x22ef10f5c48: f(5)> 4 <Greenlet "Greenlet-1" at 0x22ef12dc048: f(5)> 0 <Greenlet "Greenlet-1" at 0x22ef12dc048: f(5)> 1 <Greenlet "Greenlet-1" at 0x22ef12dc048: f(5)> 2 <Greenlet "Greenlet-1" at 0x22ef12dc048: f(5)> 3 <Greenlet "Greenlet-1" at 0x22ef12dc048: f(5)> 4 <Greenlet "Greenlet-2" at 0x22ef12dc148: f(5)> 0 <Greenlet "Greenlet-2" at 0x22ef12dc148: f(5)> 1 <Greenlet "Greenlet-2" at 0x22ef12dc148: f(5)> 2 <Greenlet "Greenlet-2" at 0x22ef12dc148: f(5)> 3 <Greenlet "Greenlet-2" at 0x22ef12dc148: f(5)> 4 Process finished with exit code 0
gevent切换执行
import gevent def f(n): for i in range(n): print(gevent.getcurrent(), i) # 用来模拟一个耗时操作,注意不是time模块中的sleep gevent.sleep(1)
g1 = gevent.spawn(f, 5) g2 = gevent.spawn(f, 5) g3 = gevent.spawn(f, 5) g1.join() g2.join() g3.join()
运行结果
F:python3.6python.exe D:/pythonProjects/pynetwork/coroutine/gevent_demo.py <Greenlet "Greenlet-0" at 0x2c45e304c48: f(5)> 0 <Greenlet "Greenlet-1" at 0x2c45e4cc048: f(5)> 0 <Greenlet "Greenlet-2" at 0x2c45e4cc148: f(5)> 0 <Greenlet "Greenlet-0" at 0x2c45e304c48: f(5)> 1 <Greenlet "Greenlet-1" at 0x2c45e4cc048: f(5)> 1 <Greenlet "Greenlet-2" at 0x2c45e4cc148: f(5)> 1 <Greenlet "Greenlet-0" at 0x2c45e304c48: f(5)> 2 <Greenlet "Greenlet-1" at 0x2c45e4cc048: f(5)> 2 <Greenlet "Greenlet-2" at 0x2c45e4cc148: f(5)> 2 <Greenlet "Greenlet-0" at 0x2c45e304c48: f(5)> 3 <Greenlet "Greenlet-1" at 0x2c45e4cc048: f(5)> 3 <Greenlet "Greenlet-2" at 0x2c45e4cc148: f(5)> 3 <Greenlet "Greenlet-0" at 0x2c45e304c48: f(5)> 4 <Greenlet "Greenlet-1" at 0x2c45e4cc048: f(5)> 4 <Greenlet "Greenlet-2" at 0x2c45e4cc148: f(5)> 4 Process finished with exit code 0
3. 给程序打补丁
from gevent import monkey import gevent import random import time # 有耗时操作时需要 monkey.patch_all() # 将程序中用到的耗时操作的代码,换为gevent中自己实现的模块 def coroutine_work(coroutine_name): for i in range(10): print(coroutine_name, i) time.sleep(random.random()) gevent.joinall([ gevent.spawn(coroutine_work, "work1"), gevent.spawn(coroutine_work, "work2") ])
运行结果
F:python3.6python.exe D:/pythonProjects/pynetwork/coroutine/gevent_test.py work1 0 work2 0 work2 1 work1 1 work1 2 work1 3 work2 2 work1 4 work1 5 work2 3 work1 6 work1 7 work2 4 work2 5 work1 8 work1 9 work2 6 work2 7 work2 8 work2 9 Process finished with exit code 0