I want to use coroutine to implement producer and receiver. My idea is using two coroutines , one for producer and one for recevier. But my understand for coroutine's send
and running mode is wrong. Here is my code :
def coroutine(func):
def start(*args,**kwargs):
cr = func(*args,**kwargs)
cr.next()
return cr
return start
class Producer(object):
def __init__(self, recevier):
self.count=1
self.producer_coroutine = self._producer()
self.receiver = receiver
@coroutine
def _producer(self):
print "Waiting"
yield
while True:
self.send("Yeah, but no, but yeah, but no")
get_feedback = (yield )
print ("get feedback %s"%get_feedback)
self.send("A series of tubes")
break
def send(self,arg):
self.receiver.receive_coroutine.send(arg)
def init_producer(self):
self.producer_coroutine.send("begin the send and receive")
class Recevier(object):
def __init__(self):
self.count=1
self.receive_coroutine=self._rececive()
self.producer = None
def setting_producer(self, producer):
self.producer = producer
@coroutine
def _rececive(self):
while True:
line = (yield)
print("Get line is : %s" %line)
self.feedback("Got it")
def feedback(self, arg):
self.producer.producer_coroutine.send(arg)
receiver = Recevier()
producer = Producer(receiver)
receiver.setting_producer(producer)
producer.init_producer()
Python give me the error:
Waiting
Get line is : Yeah, but no, but yeah, but no
Traceback (most recent call last):
File "test/test_coroutine.py", line 56, in <module>
producer.init_producer()
File "test/test_coroutine.py", line 31, in init_producer
self.producer_coroutine.send("begin the send and receive")
File "test/test_coroutine.py", line 21, in _producer
self.send("Yeah, but no, but yeah, but no")
File "test/test_coroutine.py", line 28, in send
self.receiver.receive_coroutine.send(arg)
File "test/test_coroutine.py", line 47, in _rececive
self.feedback("Got it")
File "test/test_coroutine.py", line 50, in feedback
self.producer.producer_coroutine.send(arg)
ValueError: generator already executing
Update: I find greenlet may implement the communication. Which like this :
from greenlet import greenlet
def test1():
global a
print 12, "begin switch"
gr2.switch()
a = 4
print " begin switch too"
gr2.switch()
def test2():
global a
print 56,"come from test1, to swich"
gr1.switch()
print a
print 78
a=5
gr1 = greenlet(test1)
gr2 = greenlet(test2)
gr1.switch()
When you call producer.init_producer()
, the following happens:
_producer
sends "Yeah, but no, but yeah, but no"
._rececive
receives "Yeah, but no, but yeah, but no"
and prints it._rececive
calls self.feedback
.self.feedback
sends "Got it"
to _producer
_producer
is still at the line self.send("Yeah, but no, but yeah, but no")
, because _rececive
has not yield
ed yet._producer
is not on a yield
statement, it cannot receive a send, and so an exception is thrown.Therefore, the problem is your feedback loop. I'm not sure why the feedback loop is needed, as if you comment out the send_feedback
and get_feedback
lines, the program works fine, producing:
Waiting
Get line is : Yeah, but no, but yeah, but no
Get line is : A series of tubes
Traceback (most recent call last):
File "d.py", line 58, in <module>
producer.init_producer()
File "d.py", line 32, in init_producer
self.producer_coroutine.send("begin the send and receive")
StopIteration