【协程】
1.定义:
纤程 微线程,协程本质只有一个线程在运行
2.功能原理:
通过应用层程序,记录上下文栈区,实现在程序执行过程中的跳跃,
选择可以不阻塞的部分执行,从而提高IO的执行效率
3.优点:
1.资源消耗很少
2.无需多线程那样来回切换的开销
3.无需进行同步互斥操作
4.IO并发性好
缺点:
1.无法利用计算机的多核资源
2.程序不能够一个客户端单独长时间占有服务端
4.底层实现原理:
yield–>协程的基本实现关键字
sudo pip3 install greenlet
sudo pip3 install gevent
(都是第三方模块,需要安装)
import greenlet
greenlet.greenlet()
gr.switch()
import gevent
* 将协程事件封装为函数
gevent.spawn(func,argv)
功能:
将事件变为协程事件并启动
参数:
func 传入一个函数变为协程
argv 给func函数传参
返回值:
协程对象
gevent.joinall()
功能:回收协程
gevent.sleep(n)
功能:模拟IO阻塞的情况
参数:n表示睡眠时间
from gevent import monkey
monkey.patch_all()
功能:
在导入socket模块之前使用,修改socket的IO设置行为
5.示例:
from greenlet import greenlet
def test1():
print(12)
gr2.switch()
print(34)
gr2.switch()
def test2():
print(56)
gr1.switch()
print(78)
# 生成协程对象
gr1 = greenlet(test1)
gr2 = greenlet(test2)
# 调用协程函数
gr1.switch()
在终端打印:
12
56
34
78
缺点:函数的跳跃需要人为的去切换
import gevent
def foo():
print('Running in foo')
gevent.sleep(2)
print('switch to foo again')
def bar():
print('Running in bar')
gevent.sleep(3)
print('switch to bar again')
# 将两个函数设置为协程,此时协程函数运行
f = gevent.spawn(foo)
g = gevent.spawn(bar)
# 回收协程
gevent.joinall([f,g])
在终端打印:
Running in foo
Running in bar
switch to foo again
switch to bar again
协程服务器:
import gevent
from gevent import monkey
# 需要在socket导入前执行,改变socket的属性行为
monkey.patch_all()
from socket import *
# 套接字创建
def server(port):
s = socket()
s.bind(('0.0.0.0',port))
s.listen(5)
while True:
c,addr = s.accept()
print('Connect from',addr)
gevent.spawn(handle,c)
# 处理客户端请求
def handle(c):
while True:
data = c.recv(1024)
if not data:
break
print('recv:',data)
c.send(b'Receive your message')
c.close()
if __name__ == '__main__':
server(8888)