我的问题与此问题几乎相同: Widget to Display subprocess stdout? 但更进一步。
我有以下代码(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)
&#34; longrunning&#34;的输出bash脚本是实时捕获的(出现在控制台中)但是Tkinter窗口只在子进程结束后出现!!
如何在子进程启动之前显示窗口并实时更新其内容?
答案 0 :(得分:3)
最后我找到了解决方案。 在窗口构造之后,您必须添加:
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()
答案 1 :(得分:1)
这是一个有趣的解决方案。是否有可能拥有整个工作代码?
我在问,因为我很想知道while True
如何阻止整个GUI的可用性......不是吗?
如我所料,我试过这个例子并不是真的有效。如果你使用类似“ls -Rf /
”之类的命令,你会看到while循环将使txt输出流畅。然而,两个窗口(主要和次要)将阻止大量时间。
我怀疑你需要在一个单独的线程或进程中发送print txt部分。或者,如果你使用pygtk,你可以使用像
这样的东西gobject.io_add_watch(self.ep1.stdout, # file descriptor
gobject.IO_IN, # condition
self.write_to_buffer ) # callback
实际上是为此而发明的。
答案 2 :(得分:0)
以防万一有人在找它...
log_box_1 = tk.Text(root, borderwidth=3, relief="sunken")
with subprocess.Popen("ls -la", shell=True, stdout=subprocess.PIPE, bufsize=1, universal_newlines=True) as p:
for line in p.stdout:
log_box_1.insert(tk.END, line)
来自here