本来,想给这个随笔起个更眩的名字:《跟随赖神学协程——之一》,原因嘛,自然是因为赖神的协程三篇之一(协程初接触)。不过,怕赖神k我,所以标题党还是朴素一点吧。
至于标题里的问号,是我有意加上去的。原因是在推上赖神认为“python 语言和标准库是不支持协程的(3.x部分支持)”,并且如果 python 自身支持协程,“stackless py 该有多么惭愧啊, :)”(stackless python 的协程详情请看这里)。但是因为 PEP 0342 的描述,令我很迷惑。python 自身是否可以实现协程,这个值得商榷。我不确定,保守点好,给自己个后路走。加个问号吧……如果这不算协程,大家就当我实现了“伪协程”吧。嘿嘿……
在赖神的博客里有对协程的一个简单的描述,为了说明下面的代码,特别摘抄于此:“协程是用户空间线程,操作系统其存在一无所知,所以需要用户自己去做调度,用来执行协作式多任务非常合适。”
赖神博客中的例子应当是引用了维基百科对于协程的说明。下面的代码正是基于这个伪代码实现的,同样的原因摘抄于此:
生产者:
loop |
while q is not full |
create some new items |
add the items to q |
yield to consume |
消费者
loop |
while q is not empty |
remove some items from q |
use the items |
yield to produce |
这两段伪代码,赖神的博客上已经有说明,不再累述。看看 python 如何实现这个的吧:
#!/usr/bin/evn python |
# -*- coding:utf-8 -*- |
import time |
# 生产者 |
def produce(l): |
i = 0 |
while True : |
i + = 1 |
l.append(i) |
time.sleep( 2 ) |
# 暂时跳出当前方法 |
yield i |
# 消费者 send 了以后,就又回到了这里继续执行 |
pass |
# 消费者 |
def consume(l): |
p = produce(l) |
while True : |
try : |
# 获取生产者的执行 |
i = p. next () |
# 这里完全是为了匹配伪代码而写,实际上这个 list 在这种情况下,即不会多于一个 item,也不会为空 |
while len (l) > 0 : |
print l.pop() |
except : |
# 生产者提供的所有的执行都处理完了,通过 send 返回生产者跳出的地方 |
p.send( None ) |
l = [] |
consume(l) |
这段代码是可以正常执行的,由生产者每秒产生一个数字放入 list,由消费者从 list 中取出并打印。
大家对照赖神的说明和维基百科上的内容理解一下吧。
总结一下!我对于 python 的协程的观点是:“python 自身已经提供了实现协程的基础条件,是可以很容易的实现概念中的协程。但是由于栈的问题,只能由循环的方式来实现调用。而 stackless 在 python 原有的基础上,改进了 python 在协程上的实现方式,使其代码的表达更加的自然。”
如有不对,尽请拍砖,期待赖神的协程系列二、三。继续品味协程……
Leave a Reply