python基础:协程详解
Python的yield
不但可以返回一个值,它还可以接收调用者发出的参数。
来看例子:
传统的生产者-消费者模型是一个线程写消息,一个线程取消息,通过锁机制控制队列和等待,但一不小心就可能死锁。
如果改用协程,生产者生产消息后,直接通过yield
跳转到消费者开始执行,待消费者执行完毕后,切换回生产者继续生产,效率极高:
1 #coding:utf-8 2 __author__ = 'Administrator' 3 4 def consumer(): 5 r = '[CONSUMER]初始化' 6 while True: 7 n = yield r 8 print(n) 9 if not n: 10 return 11 print('[CONSUMER] Consuming %s...' % n) 12 r = '200 OK' 13 14 def produce(c): 15 r=c.send(None) 16 print(r) 17 n = 0 18 while n < 5: 19 n = n + 1 20 print('[PRODUCER] Producing %s...' % n) 21 r = c.send(n) 22 print('[PRODUCER] Consumer return: %s' % r) 23 c.close() 24 25 c = consumer() 26 produce(c)
输出:
[CONSUMER]初始化 [PRODUCER] Producing 1... 1 [CONSUMER] Consuming 1... [PRODUCER] Consumer return: 200 OK [PRODUCER] Producing 2... 2 [CONSUMER] Consuming 2... [PRODUCER] Consumer return: 200 OK [PRODUCER] Producing 3... 3 [CONSUMER] Consuming 3... [PRODUCER] Consumer return: 200 OK [PRODUCER] Producing 4... 4 [CONSUMER] Consuming 4... [PRODUCER] Consumer return: 200 OK [PRODUCER] Producing 5... 5 [CONSUMER] Consuming 5... [PRODUCER] Consumer return: 200 OK
注意到consumer
函数是一个generator
,把一个consumer
传入produce
后:
-
首先调用
c.send(None)
启动生成器,使consumer函数先运行到yield r,将r返回值传回; -
然后,一旦生产了东西,通过
c.send(n)
切换到consumer
执行n= 那里开始往下执行完,再运行到yield r,将r返回值传回; -
consumer
通过yield
拿到消息,处理,又通过yield
把结果传回; -
produce
拿到consumer
处理的结果,继续生产下一条消息; -
produce
决定不生产了,通过c.close()
关闭consumer
,整个过程结束。
整个流程无锁,由一个线程执行,produce
和consumer
协作完成任务,所以称为“协程”,而非线程的抢占式多任务