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