生产者-消费者的协程
继续站在别人的肩膀上
转载, 单独把这部分拿出来 方便以后查找.
生产者-消费者的协程
1 |
|
1 |
|
上面这个例子是典型的生产者-消费者问题,我们用协程的方式来实现它。首先从主程序中开始看,第一句 c = consumer (),因为 consumer 函数中存在 yield 语句,python 会把它当成一个 generator(生成器,注意:生成器和协程的概念区别很大,千万别混淆了两者),因此在运行这条语句后,python 并不会像执行函数一样,而是返回了一个 generator object。
再看第二条语句 c.send (None),这条语句的作用是将 consumer(即变量 c,它是一个 generator)中的语句推进到第一个 yield 语句出现的位置,那么在例子中,consumer 中的 status = True 和 while True: 都已经被执行了,程序停留在 n = yield status 的位置(注意:此时这条语句还没有被执行),上面说的 send (None) 语句十分重要,如果漏写这一句,那么程序直接报错,这个 send () 方法看上去似乎挺神奇,等下再讲它的作用。
下面第三句 p = producer (c),这里则像上面一样定义了 producer 的生成器,注意的是这里我们传入了消费者的生成器,来让 producer 跟 consumer 通信。
第四句 for status in p:,这条语句会循环地运行 producer 和获取它 yield 回来的状态。
好了,进入正题,现在我们要让生产者发送 1,2,3,4,5 给消费者,消费者接受数字,返回状态给生产者,而我们的消费者只需要 3,4,5 就行了,当数字等于 3 时,会返回一个错误的状态。最终我们需要由主程序来监控生产者-消费者的过程状态,调度结束程序。
现在程序流进入了 producer 里面,我们直接看 yield consumer.send (n),生产者调用了消费者的 send () 方法,把 n 发送给 consumer(即 c),在 consumer 中的 n = yield status,n 拿到的是消费者发送的数字,同时,consumer 用 yield 的方式把状态(status)返回给消费者,注意:这时 producer(即消费者)的 consumer.send () 调用返回的就是 consumer 中 yield 的 status!消费者马上将 status 返回给调度它的主程序,主程序获取状态,判断是否错误,若错误,则终止循环,结束程序。上面看起来有点绕,其实这里面 generator.send (n) 的作用是:把 n 发送 generator (生成器) 中 yield 的赋值语句中,同时返回 generator 中 yield 的变量(结果)。
于是程序便一直运作,直至 consumer 中获取的 n 的值变为 3!此时 consumer 把 status 变为 False,最后返回到主程序,主程序中断循环,程序结束。