社区微信群开通啦,扫一扫抢先加入社区官方微信群
社区微信群
yield 一个对象
返回这个对象
暂停这个函数
等待下次next重新激活
def my_gen():
print('第一次执行')
a = yield 1
print('a is:', a)
print('第二次执行')
b = yield 2
print('b is:', b)
print('第三次执行')
c = yield 3
print('c is:', c)
g = my_gen()
v1 = next(g)
print(v1)
v2 = next(g)
print(v2)
v3 = next(g)
print(v3)
运行结果:send 一个对象
激活生成器
执行生成器里面的代码
遇到yield回到调用位置
def my_gen():
print('第一次执行')
a = yield 1
print('a is:', a)
print('第二次执行')
b = yield 2
print('b is:', b)
print('第三次执行')
c = yield 3
print('c is:', c)
g = my_gen()
v1 = next(g) #相当于g.send(None) ,生成器的启动需要next或者send(None),否则报错
print(v1)
v2 = g.send('cainiao')
print(v2)
v3 = g.send('xiaobai')
print(v3)
运行结果:import random
import time
#消费者
def consumer():
while True:
data = yield
print('消费者拿到:', data)
#生产者
def producer(cos):
next(cos) #激活生成器对象,让他执行到yield
while True:
item = random.randint(0, 99) #随机生产一个数
print('生产者生产了:', item)
cos.send(item) #把item给消费者,切换到消费者函数
time.sleep(2)
c = consumer() #返回一个生成器对象
producer(c)
运行结果:pip install greenlet
from greenlet import greenlet
import random
import time
#消费者
def consumer():
while True:
item = p.switch() #切换到生产者,并等待生产者传入item
print('消费者拿到:', item)
#生产者
def producer():
while True:
item = random.randint(0, 99) #随机生产一个数
print('生产者生产了:', item)
c.switch(item) #将item传给消费者,切换到消费者函数
time.sleep(2) #每生产一个就休息一些,方便我们看效果
c = greenlet(consumer) #将一个普通的函数变成协程
p = greenlet(producer)
c.switch() #运行消费者
运行结果:虽然,我们有了 基于 epoll 的回调式编程模式,但是却难以使用。即使我们可以通过配合 生成器协程 进行复杂的封装,以简化编程难度。但是仍然有一个大的问题: 封装难度大,现有代码几乎完全要重写gevent,通过封装了 libev(基于epoll) 和 greenlet 两个库。帮我们做好封装,允许我们以类似于线程的方式使用协程。以至于我们几乎不用重写原来的代码就能充分利用 epoll 和 协程 威力。
安装:pip install gevent
import gevent
from gevent import monkey
monkey.patch_socket() #打了这个补丁,下面导入的socket都会被epoll监控
import socket
def func(conn):
while True:
data = conn.recv(1024)
if data:
print('接受的数据%s'%data.decode())
conn.send(data)
else:
conn.close()
break
server = socket.socket()
server.bind(('0.0.0.0', 7001))
server.listen()
print('等待连接......')
while True:
conn, addr = server.accept()
print('{}上线'.format(addr))
gevent.spawn(func, conn) #创建一个协程
运行结果:
遇到阻塞就切换到另一个协程继续执行 !
总结:
充分利用cpu多进程,用线程来做计算密集型任务,gevent来做IO密集型任务。
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!