2010-11-22 7 views
3

複数のTCP接続が開いているシングルスレッドスクリプトで対話型コンソールを使用したいと考えています。これは、スレッドをブロックする標準入力を持つことができないことを意味します。シングルスレッドのPythonスクリプトでコンソールを使用する

これを行う簡単な方法はありますか?それとも、私はコンソールを自分のスレッドに入れてそれをやるべきなのでしょうか?

+0

。あなたが本当に記述していると思われるものは、多かれ少なかれウェブサーバーです。 私はとにかく考え続けていること –

答えて

0

シングルスレッドでもマルチスレッドでもかまいませんが、スレッドを使用しない場合は、ポーリングを使用する必要があります(Cではpoll(2)などを使用します)。コンソールおよび/またはTCP接続が入力準備完了です。

+0

その部分は私が得た。私は、コンソールからの入力をユーザーから読み込み、同時に物を出力する便利な方法について考えていました。ライブラリやオープンソースアプリケーションで既に行われているように、私はそれを見ることができます。 – Blixt

3

あなたにInteractiveConsole(組み込みから「コード」モジュール)をサブクラス化することができ、ベース にInteractiveConsoleのプッシュ()メソッドに転送する前たStringIOインスタンスにSTDOUT/stderrを リダイレクトラッパーにプッシュ()メソッドをオーバーライド 。あなたのラッパーは2タプルを返すことができます (more、result)ここで 'more'はInteractiveConsoleが の入力を期待するかどうかを示し、 'result'はInteractiveConsole.push()が StringIOインスタンスに書き込んだものです。

それはそれよりも硬く聞こえます。

import sys 
from cStringIO import StringIO 
from code import InteractiveConsole 
from contextlib import contextmanager 

__all__ = ['Interpreter'] 


@contextmanager 
def std_redirector(stdin=sys.stdin, stdout=sys.stdin, stderr=sys.stderr): 
    """Temporarily redirect stdin/stdout/stderr""" 

    tmp_fds = stdin, stdout, stderr 
    orig_fds = sys.stdin, sys.stdout, sys.stderr 
    sys.stdin, sys.stdout, sys.stderr = tmp_fds 
    yield 
    sys.stdin, sys.stdout, sys.stderr = orig_fds 


class Interpreter(InteractiveConsole): 
    """Remote-friendly InteractiveConsole subclass 

    This class behaves just like InteractiveConsole, except that it 
    returns all output as a string rather than emitting to stdout/stderr 

    """ 
    banner = ("Python %s\n%s\n" % (sys.version, sys.platform) + 
       'Type "help", "copyright", "credits" or "license" ' 
       'for more information.\n') 

    ps1 = getattr(sys, "ps1", ">>> ") 
    ps2 = getattr(sys, "ps2", "... ") 


    def __init__(self, locals=None): 
     InteractiveConsole.__init__(self, locals=locals) 
     self.output = StringIO() 
     self.output = StringIO() 

    def push(self, command): 
     """Return the result of executing `command` 

     This function temporarily redirects stdout/stderr and then simply 
     forwards to the base class's push() method. It returns a 2-tuple 
     (more, result) where `more` is a boolean indicating whether the 
     interpreter expects more input [similar to the base class push()], and 
     `result` is the captured output (if any) from running `command`. 

     """ 
     self.output.reset() 
     self.output.truncate() 
     with std_redirector(stdout=self.output, stderr=self.output): 
      try: 
       more = InteractiveConsole.push(self, command) 
       result = self.output.getvalue() 
      except (SyntaxError, OverflowError): 
       pass 
      return more, result 

チェックアウトこの完全な例、UDPソケットからの入力を受け付けます:ここで基本的な前提だ

スタート2つのコンソールと1でserver.pyを実行し、もう一方はclient.py。 すべてのコマンドが が評価のためにserver.pyにラウンドトリップされていても、client.pyに表示される内容はPythonの 通常の対話型インタプリタと区別できません。

もちろん、このようなソケットを使用することは非常に安全ですが、 は外部入力を非同期に評価する方法を示しています。あなたは 入力ソースを信頼する限り、 はあなたの状況にそれを適応させることができるはずです。物事は「面白い」を取得するときに誰かの種類:

while True: continue 

しかし、それは全く別の問題だ... :-)

アイブ氏は多く、最近この質問を訪問されまし
関連する問題