潭州课堂25班:Ph201805201 并发(协程) 第十五课 (课堂笔记)
#斐波那契 def fid(n): res = [] indx = 0 a = 0 b = 1 while indx < n : res.append(b) a,b = b,a+b indx += 1 return res print(fid(1000))
# 生成器 def fid(n): indx = 0 a = 0 b = 1 while indx < n : yield b # 暂停并返回 跳出函数 res.append(b) a,b = b,a+b indx += 1 f = fid(10) print(f) print(next(f))
# 生成器 import time def fid(n): indx = 0 a = 0 b = 1 while indx < n : data = yield b # 暂停并返回 跳出函数 time.sleep(data) a,b = b,a+b indx += 1 f = fid(10) # # 使用 send 前,要 next 下 # f.__next__() # 或者 先 send ( None ) f.send(None) print(f.send(2)) print(f.send(2)) print(f.send(2))
# 协程 :非抢占式多任务子程序组件 import greenlet # pip install greenlet from greenlet import greenlet def tast_1(): print(11111) gr2.switch() print(22222) def tast_2(): print(33333) print(44444) gr1.switch() gr1 = greenlet(tast_1) gr2 = greenlet(tast_2) gr1.switch() # 调用协程,
######
11111
33333
44444
22222
# 协程 传参 import greenlet # pip install greenlet from greenlet import greenlet def tast_1(): print(11111) a = gr2.switch() # 传参 print(22222) print(a) def tast_2(): print(33333) print(44444) gr1.switch(123) # 传参 gr1 = greenlet(tast_1) gr2 = greenlet(tast_2) gr1.switch() # 调用协程, ######### 11111 33333 44444 22222 123
遇到阻塞时自动切换,
# gevent HTTP 请求 from gevent import monkey;monkey.patch_all() # 猴子补丁 import gevent '''当 greenlet 遇到一个 IO 操作垢时候 ,自动切换到其他的 greenlet''' import requests # import time def get_res(pn): print('开始',pn) requests.get('https://www.baidu.com') # 这里耗时发生阻塞 # time.sleep(3) print('结束',pn) # gevent.spawn 启动协程 ta = [gevent.spawn(get_res,i) for i in range(5)] # time.sleep(2) gevent.joinall(ta) # gevent.joinall(ta,timeout=1) # spawn 创建一个 gevent 的的协程对象,开始运行, # 为什么 ta = [gevent.spawn(get_res,i) for i in range(5)] # 不打印,?因为他运行为立马退出,不会打印, # joinall 等待所有 greenlet 执行完毕,
如果没有使用猴子补丁
# 生产者与消费者 import gevent import random from queue import Queue # 队列 q = Queue(2) def con(): # 消费者 while True: print(q.qsize()) iten = q.get() print('删除一个数据{}'.format(iten)) def pro(): # 生产者 while True: print(q.qsize()) iten = random.randint(0,99) # 如果没有猴子补丁,程序将阻塞在这里, q.put(iten) print('添加一个数据{}'.format(iten)) p1 = gevent.spawn(pro) c1 = gevent.spawn(con) gevent.joinall([p1,c1])
########
0
添加一个数据32
1
添加一个数据22
2
在 gevent 有 queue 队列,也可实现相互切换
在上边代码中引入
from gevent.queue import Queue
引入猴子补丁
from gevent import monkey;monkey.patch_all()# 猴子补丁
# 生产者与消费者 import gevent from gevent import monkey;monkey.patch_all() # 猴子补丁 import random from queue import Queue # 队列 q = Queue(2) def con(): # 消费者 while True: print(q.qsize()) iten = q.get() print('删除一个数据{}'.format(iten)) def pro(): # 生产者 while True: print(q.qsize()) iten = random.randint(0,99) q.put(iten) print('添加一个数据{}'.format(iten)) p1 = gevent.spawn(pro) c1 = gevent.spawn(con) gevent.joinall([p1,c1])
0
添加一个数据57
1
添加一个数据25
2
2
删除一个数据57
1
删除一个数据25
0
协程,猴子补丁,实现并发服务器
from gevent import monkey;monkey.patch_all() import socket import gevent sever = socket.socket() sever.bind(('',10000)) sever.listen(5) print('服务器开启') def func(conn): while True: data = conn.recv(1024) if data: print(data) else:break while True: conn,addr = sever.accept() print(addr) gevent.spawn(func,conn)