显示tkinter小部件中subprocess的实时输出

我的问题是几乎相同的这一个: 小工具来显示subprocess标准输出? 但更进一步。

我有以下代码(python2.7):

def btnGoClick(p1): params = w.line.get() if len(params) == 0: return # create child window win = tk.Toplevel() win.title('Bash') win.resizable(0, 0) # create a frame to be able to attach the scrollbar frame = ttk.Frame(win) # the Text widget - the size of the widget define the size of the window t = tk.Text(frame, width=80, bg="black", fg="green") t.pack(side="left", fill="both") s = ttk.Scrollbar(frame) s.pack(side="right", fill="y") # link the text and scrollbar widgets s.config(command=t.yview) t.config(yscrollcommand=s.set) frame.pack() process = subprocess.Popen(["<bashscript>", params], shell=False, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) while True: out = process.stdout.readline() if out == '' and process.poll() is not None: break print out t.insert(tk.END, out) 

“longrunning”bash脚本的输出是实时捕获的(出现在控制台中),但是Tkinter窗口只能在subprocess结束后出现!

我怎样让窗口出现在子stream程开始之前并实时更新其内容?

最后我find了解决办法。 在窗口build设之后,您必须添加:

 frame.pack() # force drawing of the window win.update_idletasks() 

然后,在每一行插入小部件之后,还必须在小部件上使用相同的方法强制刷新。

 # insert the line in the Text widget t.insert(tk.END, out) # force widget to display the end of the text (follow the input) t.see(tk.END) # force refresh of the widget to be sure that thing are displayed t.update_idletasks() 

这是一个有趣的解决scheme。 这将有可能有整个工作代码?

我在问,因为我很奇怪while True是如何阻止整个GUI的可用性的?不是吗?

怀疑,我试过,这个例子是不是真的工作。 如果你使用“ ls -Rf / ”这样的命令,你会发现while循环会使得txt输出stream畅地运行。 然而,这两个窗口(主要和次要)将阻止大的时间。

我怀疑你需要在一个单独的线程或过程中发送打印TXT部分。 或者,如果你使用pygtk,你可以使用类似的东西

 gobject.io_add_watch(self.ep1.stdout, # file descriptor gobject.IO_IN, # condition self.write_to_buffer ) # callback 

这实际上是为此而发明的。