本来,想给这个随笔起个更眩的名字:《跟随赖神学协程——之一》,原因嘛,自然是因为赖神的协程三篇之一(协程初接触)。不过,怕赖神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