生成器
通过生成器来实现对函数的反复输入和输出,这样的输入和输出同样可以用来传递数据
def func():
while True:
y = yield # 接收数据
print(y)
a = func()
# 必须要通过next()预激活,先到达yield位置,不然接收不到send发送过来的数据
next(a)
# 发送数据
a.send(111)
a.send(222)
a.send(333)
生成器实现协程
import time
# 消费者:接收数据,处理数据
def consumer():
while True:
y = yield
time.sleep(1)
print('处理了数据', y)
# 生产者:生产数据
def producer():
c = consumer()
next(c)
for i in range(10):
print('生产了数据', i)
c.send(i)
producer()
greent实现协程
greent:生成器实现协程非常不方便,尤其很多协程的时候,使用greenlet就要方便很多
而这个模块来自于Python的一个衍生版 Stackless Python原生的协程(常见是标准Python是CPython),将其协程单独拿出来打包成模块,因此性能要比生成器强很多
注意:这里并没有解决IO阻塞的问题,但是我们使用这个时间来做别的事情了,一般在工作中我们都是进程+线程+协程的方式来实现并发,以达到最好的并发效果
import time
from greenlet import greenlet
def producer():
for i in range(10):
print(f'生产了数据{i}')
time.sleep(1)
con.switch(i) # 切换到消费者
print(f'第{i}次生产消费完成')
def consumer():
while True:
var = pro.switch() # 等待数据的发送
print(f'消费了数据{var}')
pro = greenlet(producer)
con = greenlet(consumer)
con.switch() # 让消费者进入等待的状态
gevent实现并发服务器
gevent封装了epoll和greenlet,在使用的时候要更加方便
同时实现了IO阻塞时的自动切换
from gevent import monkey;
monkey.patch_all()
import gevent
import socket
server = socket.socket()
server.bind(('127.0.0.1', 5959))
server.listen(100)
def func_gevent(conn):
while True:
recv_data = conn.recv(1024)
if recv_data:
print(recv_data)
conn.send(recv_data)
else:
conn.close()
break
while True:
conn, addr = server.accept()
# 把需要执行的任务和参数放入协程中
gevent.spawn(func_gevent,conn)
gevent实现生产者和消费者模型
from gevent import monkey;
monkey.patch_all()
from gevent.queue import Queue
import gevent
q = Queue(3)
def prodecer(q):
for i in range(20):
print(f'生产了数据{i}')
q.put(i)
def consumer(q):
for i in range(20):
var = q.get()
print(f'消费了数据{var}')
实现异步
from gevent import monkey;
monkey.patch_all()
from gevent.queue import Queue
import gevent
q = Queue(3)
def prodecer(q):
for i in range(20):
print(f'生产了数据{i}')
q.put(i)
def consumer(q):
for i in range(20):
var = q.get()
print(f'消费了数据{var}')