04. 协程(微线程)
一、协程基础
1. 定义
纤程、微线程。
是非抢占式多任务产生子程序的计算机组件。协程允许不同入口在同一位置暂停或者开始。简单来说,协程就是可以暂停执行的函数
典型的抢占式设计,暂停执行的时候就会开辟新的管道
yield
是实现上述函数的基本关键字,包含yield
的函数可以暂停执行,并且返回函数内部,继续执行
def fun():
print("启动生成器")
yield 1
print("生成器玩成")
msg = fun()
print(next(msg))
print(next(msg))
以上代码会出现报错
StopIteration
next
希望得到下一个迭代值,如果有记录上下文,等待再次执行
协程的本质就是一个单进程程序,不会使用计算机多核资源,但是可以在应用层形成多个函数任务都被执行的形态,以处理多个任务。
资源占用少
2. 原理
协程是记录一个函数的上下文栈帧,协程调度切换时会将记录的上下文保存,在切换回来时进行调取,回复原有的执行内容,以便从暂停的位置继续执行。
3.优缺点
3.1 优点
- 协程完成多任务占用计算机资源少
- 协程在多任务间切换开销小
- 协程是单线程无需进行同步互斥处理
3.2 缺点
- 协程无法利用计算机多核资源
4.协程模块
4.1 greenlet
4.1.1 安装
sudo pip install greenlet
4.1.2 函数
greenlet.greenlet(func)
功能: 创建协程对象
参数: 协程函数
g.switch()
功能:执行对应的协程函数
from greenlet import greenlet
def func1():
print('执行func')
g2.switch()
print('结束func')
def func2():
print('执行func2')
g1.switch()
print('结束func2')
# 生成协程对象
g1 = greenlet(func1)
g2 = greenlet(func2)
g1.switch() # 执行func1协程
4.2 gevent
4.2.1 安装
sudo pip install gevent
4.2.2 函数
gevent.spawn(func,argv,...)
功能:生成协程对象
参数: func 协程函数
argv 给func传递参数
返回值: 协程对象
gevent.joinall(list)
功能:阻塞等待协程事件执行完毕
参数:list 协程对象列表
gevent.sleep(sec)
功能:gevent睡眠阻塞
参数:睡眠时间
gevent协程只有在遇到gevent指定的阻塞行为才会触发协程之间的跳转
4.2.3 gevent 阻塞触发方法
from gevent import monkey
e.g. 将socket模块下的所有阻塞转换为gevent阻塞
monkey.patc_socket()
from socket import *
注意:脚本插件函数必须要在导入模块之前执行
import gevent
from gevent import monkey
monkey.patch_all() # 执行脚本函数,修改原有阻塞
from socket import *
# 客户端处理函数
def handler(c):
while True:
data = c.recv(1024)
if not data:
break
print(data.decode())
c.send(b'OK')
c.close()
s = socket()
s.bind(('0.0.0.0',8888))
s.listen(5)
while True:
c, addr = s.accept()
print("来自%s的连接"%addr[0])
# handler(c) # 循环方案
gevent.spawn(handler,c)