Reputation: 2839
I'm trying coroutines pipeline according to http://www.dabeaz.com/coroutines/Coroutines.pdf
The question is, how can I get value from the sink
rather than only print it?
Take this code for example
def coroutine(func):
def start(*args, **kwargs):
cr = func(*args, **kwargs)
next(cr)
return cr
return start
@coroutine
def produce(target):
while True:
n = (yield)
target.send(n*10)
@coroutine
def sink():
try:
while True:
n = (yield)
print(n)
except GeneratorExit:
pass
sk = sink()
pipe = produce(sink())
With this code I get:
>>> pipe.send(10)
100
Then I want to get the return value rather than print it, I try to yield from sink:
@coroutine
def sink():
try:
while True:
yield (yield)
except GeneratorExit:
pass
But it seems not working, pipe.send(10)
still returns None
rather than a generator.
So how shall I get the return value?
Upvotes: 15
Views: 11287
Reputation: 101052
Why should pipe.send
return a generator? And what are you going to do with the returned value?
Whatever it is, it should be done in sink
.
You could, however, change your functions to
@coroutine
def produce(target):
while True:
n = (yield)
yield target.send(n*10)
@coroutine
def sink():
try:
while True:
yield (yield)
except GeneratorExit:
pass
to yield the value yielded by target
, so pipe.send(10)
will just return 100
instead of printing it.
But now you mix the producer and the consumer, which will potentially give you some headache.
In response to your comment:
from collections import defaultdict
def coroutine(func):
def start(*args, **kwargs):
cr = func(*args, **kwargs)
next(cr)
return cr
return start
@coroutine
def produce(key, target):
while True:
n = (yield)
target.send((key, n*10))
class Sink(object):
def __init__(self):
self.d = defaultdict(lambda: None)
self.co = self.sink()
def send(self, *args):
self.co.send(*args)
@coroutine
def sink(self):
try:
while True:
key, n = yield
self.d[key] = max(self.d[key], n)
except GeneratorExit:
pass
sk = Sink()
pipeA = produce("A", sk)
pipeB = produce("B", sk)
pipeA.send(10)
pipeA.send(20)
pipeA.send(40)
pipeB.send(20)
pipeB.send(40)
pipeB.send(60)
print sk.d.items() # [('A', 400), ('B', 600)]
Upvotes: 3