2012-04-28 7 views
2

私はツイストで簡単なエコークライアントを書こうとしています。これはキーボード入力をサーバに送信し、ユーザーが 'q'を入力して終了します。要するに、私はちょうどthis pageにある単純なエコークライアント(および亜種)を変更しようとしています。セクシーではなく、基本だけ。シンプルなツイストエコークライアント

私は非常に基本的なイベントループに苦しんでいます。停止した原子炉はループ内で原子炉を始動/停止できないようです。restartedです。原子炉を止めなければ、キーボード入力を得る次のラインには決して行きません。

私のエコークライアントを動作させる助けがあれば、大歓迎です。

from twisted.internet.protocol import ClientFactory 
from twisted.protocols.basic import LineReceiver 
from twisted.internet import reactor 

class EchoClient(LineReceiver): 
    end="Bye-bye!" 
    def connectionMade(self): 
     #only write and end transmission if the message isn't empty 
     if len(self.factory.message) > 0: 
      self.sendLine(self.factory.message) 
      self.sendLine(self.end) 
     else: 
     #Else just terminate the connection 
      self.transport.loseConnection() 

    def lineReceived(self, line): 
     print "receive:", line 
     if line==self.end: 
      self.transport.loseConnection() 

class EchoClientFactory(ClientFactory): 
    message = "" 

    def buildProtocol(self, address): 
     p = EchoClient() 
     p.factory = self 
     return p 

    def clientConnectionFailed(self, connector, reason): 
     reactor.stop() 

    def clientConnectionLost(self, connector, reason): 
     reactor.stop() 

def main(): 

    s = raw_input('Text to send (''q'' to terminate): ') 
    while s != 'q': 
     factory = EchoClientFactory() 
     factory.message = s 
     reactor.connectTCP('localhost', 8000, factory) 

     #This is bad because reactor cannot be restarted once it's been stopped 
     reactor.run() 

     s = raw_input('Text to send(''q'' to terminate): ') 

if __name__ == '__main__': 
    main() 
+0

[python twisted stdioの複数の接続で、相互作用のためのコマンドプロンプトが表示されるサーバーへの複数の接続](http://stackoverflow.com/questions/2311844/python-twisted-stdio-multiple-connections-to-a-server) -with-a-command-prompt-for) –

+0

本当に重複しているわけではありません。jbreicisが提供した答えは、そこの回答よりはるかに優れています。 – CadentOrange

+0

私の答えは、特定のタスクの方が良いわけではありません。私の答えでは、従来のブロッキングコードをtwisted.Howeverと互換性を持たせる方法を説明するために、より多くのことを試していましたが、deferToThreadは最も簡単で醜い方法です。通常、あなたは "ネイティブ"ツイストオルタナティブを見つけることができるはずです。ライン入力に関しては、より良いツイストネイティブアプローチがツイストの例のセクションで提供されています。http://twistedmatrix.com/trac/browser/trunk/doc/core/examples/stdin.py – jbreicis

答えて

3

あなたのプログラムalltogeatherを終了させない限り、原子炉を再起動または停止したいという非常にまれなケースがあります。あなたのブロックに遭遇した場合はブロックを引き起こします。データベースのアクセス、長い計算、またはあなたの場合はraw_inputのいずれかで、次のいずれかを行う必要があります:ねじれた代替(データベースの場合はtwisted.enterprise.adabi)を見つけたり、 コードをデブロックする最も簡単な方法は、twisted.internet.threadsのdeferToThreadを利用して、ブロックビットをスレッドに移動することです。 この例を考えてみましょう:

from twisted.internet.threads import deferToThread as __deferToThread 
from twisted.internet import reactor 

def mmprint(s): 
    print(s) 

class TwistedRAWInput(object): 
    def start(self,callable,terminator): 
     self.callable=callable 
     self.terminator=terminator 
     self.startReceiving() 
    def startReceiving(self,s=''): 
     if s!=self.terminator: 
      self.callable(s) 
      __deferToThread(raw_input,':').addCallback(self.startReceiving) 


tri = TwistedRAWInput() 
reactor.callWhenRunning(tri.start,mmprint,'q') 
reactor.run() 

raw_inputは、すべての新しい行に延期callbacking、外部のスレッドで起こるとあなたは、原子炉を停止する必要がないだろう。

+0

あなたの答えをありがとう。それはうまくいくように見えますが、私はTwistedの学習曲線が本当に急であると人々が述べている理由を知り始めています!私は自分でそれを理解することはできませんでした。 – CadentOrange

+0

それは急ではありません。基本的には、コンセプトを得るには非常に急なバンプだけです。その後、それはそこにある最良のフレームワークです。 – jbreicis