Python之协程(coroutine)
标签(空格分隔): Python进阶
coroutine和generator的区别
generator是数据的产生者。即它pull data 通过 iteration
coroutine是数据的消费者。它push data into pipeline 通过 send
generator的通常用法
generator的作用是可以作为data pipeline使用.
例如可以使用coroutine来做filter,
或者多路的broadcast。
generator通常是yield和for的运用。
示例代码1:
def fib():
a, b = 0, 1
while True:
yield a
a, b = b, a+b
for i in fib():
print(i)
用yield接收data,通过for循环将每一步data输出。
下面介绍coroutine, 它的yield接收外部value,而不是保存内部value。
def grep(pattern):
print("Searching for", pattern)
while True:
line = (yield)
if pattern in line:
print line
此处的 yield并不包含任何value,它接受外部.send()方法传过来的value.
search = grep('coroutine')
next(search)
# Output: Searching for coroutine
search.send("I love you")
search.send("Don't you love me?")
search.send("I love coroutines instead!")
# Output: I love coroutines instead!
search.close()
先通过next(),start这个coroutine.
之后每一次调用send(),将参数通过yield传入line中。同时相当于自动运行.next()到下一个value. 最终调用.close()关闭这个协程。
示例1:作为filter使用
import time
def follow(thefile, target):
thefile.seek(0,2) # Go to the end of the file
while True:
line = thefile.readline()
if not line:
time.sleep(0.1) # Sleep briefly
continue
target.send(line)
@coroutine
def printer():
while True:
line = (yield)
print line
@coroutine
def grep(pattern,target):
while True:
line = (yield) # Receive a line
if pattern in line:
target.send(line) # Send to next stage
f = open("access-log")
follow(f,grep('python',printer()))
dataflow如下:###
follow将file中的每一行读取,send到coroutine中,grep查找匹配的line,send到下一个coroutine中,printer接收send过来的data,并且输出。 完成整个filter的流程。
follow()-> grep() : send()
grep() -> printer():send()
示例2:作为broadcasting使用
@coroutine
def broadcast(targets):
while True:
item = (yield)
for target in targets:
target.send(item)
f = open("access-log")
p = printer()
follow(f,
broadcast([grep('python',p),
grep('ply',p),
grep('swig',p)])
)
这样就将不同的pattern传入到了不同的coroutine中去,达到了broadcast的目的。
follow-> broadcast: send()
broadcast -> grep('python'): send()
broadcast -> grep('ply') : send()
broadcast -> grep('swig') : send()
grep('python') -> printer:
grep('ply')-> printer:
grep('swig')-> printer:
关于coroutine的更多用法,可见pdf:
http://www.dabeaz.com/coroutines/Coroutines.pdf