0

私が開発しているアプリケーションには、初期化時に Popen を にリダイレクトすることによって suprocess を開始するスレッドがありstdoutますPIPErun()パイプとイベントの両方で待機する必要があります。
パイプの出力はテキストビューに出力する必要があります。
イベントが設定されると、スレッドは から戻るのを停止する必要がありrun()ます。

私の解決策は

  • タイムアウトした select.select によってパイプで待機する
  • 次に、選択が返された場合、パイプは読み取り可能です
    • パイプから 1 バイトを読み取るので、この読み取りはブロックできないと確信しています
    • 改行を受け取るまで、バイトをバイト配列に格納します
      • bytearray を textviev に出力する
  • イベントのテスト

これは機能しますが、1回に1バイトを読み取るのは非常に非効率的
です。より効率的なソリューションが存在するのではないかと思っています。

これは私のコードのスニペットです:

class ProcessEcho(threading.Thread):

    def __init__(self,environ,command_line,textbuffer,on_process_exited_cb):
        super(ProcessEcho,self).__init__()

        self.textbuffer = textbuffer
        self.on_process_exited_cb = on_process_exited_cb

        self.popen = subprocess.Popen(command_line,stdout = subprocess.PIPE, stderr = subprocess.STDOUT,bufsize=0,env=environ)

        self.exit_event = threading.Event()

        self.daemon = True
        self.start()

    def get_pid(self):
        return self.popen.pid

    def stop(self):
        self.exit_event.set()

    def update_textbuffer(self,string):
        self.textbuffer.insert(self.textbuffer.get_end_iter(),string)

    def run(self):
        buffer = bytearray()
        while True:
            rl,wl,xl = select.select([self.popen.stdout], [], [], 1)

            if len(rl):
                r = self.popen.stdout.read(1)
                if r=='':
                    self.popen.communicate()
                    GObject.idle_add(self.on_process_exited_cb)
                    return
                else:
                    buffer.append(r)

                    if r == "\n":
                        GObject.idle_add(self.update_textbuffer,str(buffer))
                        buffer = bytearray()
            if self.exit_event.is_set():
                self.popen.communicate()
                GObject.idle_add(self.on_process_exited_cb)
                return
4

1 に答える 1

0

ブロックせずにストリームを読み取るには、Queue.get_nowait() を使用します。

于 2013-01-22T04:44:27.677 に答える