2015-04-01 2 views
0

Я хочу использовать сопрограмму для реализации производителя и приемника. Моя идея заключается в использовании двух сопрограмм, один для производителя и один для приемника. Но я понимаю, что для coroutine's send и режим работы неправильный. Вот мой код:Понимать производителя и приемника с помощью сопрограммы в python

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 дает мне ошибку:

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 

Обновление: Я считаю greenlet может осуществлять связь. Который так:

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() 

ответ

3

При вызове producer.init_producer(), происходит следующее:

  • _producer посылает "Yeah, but no, but yeah, but no".
  • _rececive получает "Yeah, but no, but yeah, but no" и печатает его.
  • _rececive звонки self.feedback.
  • self.feedback посылает "Got it" в _producer
  • Однако _producer все еще находится на линии self.send("Yeah, but no, but yeah, but no"), потому что _rececive не имеет yield ред еще.
  • Поскольку _producer не находится в операторе yield, он не может получать посылку, и поэтому создается исключение.

Таким образом, проблема заключается в вашей обратной связи. Я не знаю, почему петля обратной связи необходима, как если бы вы закомментировать send_feedback и get_feedback линии, программа отлично работает, производя:

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 
+0

В некоторых ситуациях, я хочу приемник может WARK до производителя, поэтому продюсер может продолжать, точно так же, как переключатель greenlet. В любом случае вы объясните, почему мой код не удался. Мне интересно, почему _producer все еще находится на линии self.send? Может ли он просто отправить и перейти к следующей линии? Это кажется разумным, это сопрограмма и посылать что-то и продолжать. – jiamo

+0

@jiamo Нет, он отправляет и ждет отправки до конца, что никогда не происходит, как я объясняю выше. – matsjoyce

+0

ОК. похоже, что coroutine не похож на нить. – jiamo