文章目录
- 协程
- 一、协程基本概述
- 二、用生成器 yiled 实现协程
- 三、greenlet
- 四、gevent
- 补充: mokey补丁模块
协程
一、协程基本概述
协程 又称为微线程,纤程,英文名(corotine)。从技术的角度来说,“协程就是你可以暂停执行的函数”。可以理解成生成器一样。一句话总结协程就是一个线程里可以协调cpu来完成多任务,提高效率,减少资源的浪费。
协程存在的意义:对于多线程应用,CPU通过切片的方式来切换线程间的执行,线程切换时需要耗时(保存状态,下次继续)。协程,则只使用一个线程(单线程),在一个线程中规定某个代码块执行顺序。
协程的使用场景:当程序中存在大量不需要CPU操作的时(IO),适用协程;
协程工作原理如下图:
二、用生成器 yiled 实现协程
1、创建 work1 生成器。
2、创建work2 生成器
3、获取生成器,用next() 运行生成器
import time
def work1():
while True:
print("------我是work1------")
time.sleep(1)
yield #程序碰见 yield 会返回一个生成器。
def work2():
while True:
print("------我是work2------")
time.sleep(1)
yield
if __name__ == '__main__':
while True:
next(work1())
next(work2())
三、greenlet
greenlet 是第三方模块。使用greenlet 可以实现协程,可以自行调度微线程,即协程。generator 实现的协程在yiled value 时只能将 value返回给调用者(caller)。而在greenlet中,target.switch(value)可以切换到指定的协程(target),然后yield value。greenlet 用switch 来表示协程的切换,从一个协程切换到另一协程需要显示指定。
greenlet 实现协程的步骤:
1、导入模块 from greenlet import greenlet
2、创建任务 work1 work2
3、创建greenlet 的对象。 g1 = greenlet(work1) ,g2 = greenlet(work1)
4、切换任务 work1里(g2.switch), work2(g1.switch) 两个任务来回切换。
import time
from greenlet import greenlet
def work1():
while True:
print("------我是work1------")
time.sleep(1)
g2.switch()
def work2():
while True:
print("------我是work2------")
time.sleep(1)
g1.switch()
if __name__ == '__main__':
g1 = greenlet(work1)
g2 = greenlet(work2)
g1.switch()
四、gevent
greenlet 已经是实现了协程,但是这个还需要人工切换,有点麻烦。由于IO操作非常耗时,经常使程序处于等待状态,有了gevent 为我们自动切换协程,就保证总有greenlet在运行,而不是等待IO。
grevent也是第三方库。
如何用gevent 实现协程:
1、导入gevent 模块 improt gevent
2、指派任务 gevent.spawn(函数名,参数1,参数2,…) g1 = gevent.spawn(work1)。g1.join , g2.join 让主线程等待程序完成后退出(让程序阻塞)。
有一个耗时操作,1.gevent.sleep(0.5)替换 time.sleep(0.5);2.打补丁让gevent 识别 time.sleep()。
打补丁是在不修改程序源代码的情况下,为程序增加新的功能。
补充: mokey补丁模块
如何打补丁:1) 导入 monkey 模块 from gevent import monkey
2)破解所有补丁 monkey.patch_all()
猴子补丁主要有以下几个用处:
1、在运行时替换方法、属性等
2、在不修改第三方代码的情况下增加新的功能
3、在运行时为内存中的对象增加patch而不是在磁盘的源代码中增加。
#导入模块
from gevent import monkey
#破解所有
monkey.patch_all()
from gevent import monkey #导入monkey 补丁模块
monkey.patch_all()
import time
import gevent
def work1():
while True:
print("------我是work1------",gevent.getcurrent()) #gevent.getcurrent() 查看哪个协程在执行
# gevent.sleep(1)
time.sleep(1)
def work2():
while True:
print("------我是work2------",gevent.getcurrent())
# gevent.sleep(1)
time.sleep(1)
if __name__ == '__main__':
g1 = gevent.spawn(work1)
g2 = gevent.spawn(work2)
# 让主线程等待程序完成后退出,(让程序阻塞)
g1.join()
g2.join()