在我正在开发的应用程序中,我有一个线程,在初始化时通过 Popen 重定向stdout
来启动一个 suprocess PIPE
。在run()
我需要在管道和事件上等待。
管道的输出必须在文本视图上输出。
设置事件后,线程必须停止从run()
.
我的解决方案是
- 通过超时的 select.select 在管道上等待
- 那么如果选择返回管道是可读的
- 从管道中读取一个字节,所以我确信这个读取不会阻塞
- 将字节存储在字节数组中,直到我收到换行符
- 将字节数组输出到 textviev
- 测试事件
这可行,但每次读取 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