Python Tkinter:从子流程输出实时更新GUI
我搜索了整个互联网来回答我的问题,但似乎没有人有相同的问题:我正在尝试从子流程输出动态更新tkinter GUI,如果我在eclipse中启动GUI,这很好。但是,如果在文件资源管理器或visual studio中运行它,“stdout.readline”命令将等待,直到子进程完成。只有这样,完整的输出才会打印到我的文本区域。。。我正在使用一个线程,我尝试了两种方法:一种是“App.py”中显示的,另一种是使用“read\u update”方法(而不是使用“reader\u thread”和“update”方法) 有趣的旁注:Test.py中的sys.argv命令不会返回我的字符串“var_Test”。谁能告诉我为什么 我的课程是: GUI.pyPython Tkinter:从子流程输出实时更新GUI,python,tkinter,subprocess,python-multithreading,Python,Tkinter,Subprocess,Python Multithreading,我搜索了整个互联网来回答我的问题,但似乎没有人有相同的问题:我正在尝试从子流程输出动态更新tkinter GUI,如果我在eclipse中启动GUI,这很好。但是,如果在文件资源管理器或visual studio中运行它,“stdout.readline”命令将等待,直到子进程完成。只有这样,完整的输出才会打印到我的文本区域。。。我正在使用一个线程,我尝试了两种方法:一种是“App.py”中显示的,另一种是使用“read\u update”方法(而不是使用“reader\u thread”和“u
import Tkinter as tk
from App import App
if __name__ == '__main__':
root = tk.Tk()
app = App(root)
root.protocol("WM_DELETE_WINDOW", app.quit)
root.mainloop()
App.py
#App.py
import Tkinter as tk
import tkFont as tkfont
import subprocess
from subprocess import Popen
from subprocess import PIPE
from itertools import islice
from threading import Thread
from ttk import Scrollbar
from Tkinter import *
from Queue import Queue, Empty
class App():
def __init__(self, root):
self.root = root
self.root.title_font = tkfont.Font(family = "Helvetica", size = 18, weight = "bold", slant = "italic")
Grid.columnconfigure(self.root, 5, weight = 1)
button_ok = tk.Button(self.root, text = "OK", width = 10, command = lambda: self.on_okay())
button_ok.grid(row = 7, column = 0, padx = (20,0), pady = 10, sticky = W)
xscrollbar = Scrollbar(self.root, orient=HORIZONTAL)
xscrollbar.grid(row=8, column=1, columnspan=4, sticky=E + W)
yscrollbar = Scrollbar(self.root, orient=VERTICAL)
yscrollbar.grid(row=8, column=5, sticky=N + S)
self.textarea = Text(self.root, wrap=NONE, bd=0,
xscrollcommand=xscrollbar.set,
yscrollcommand=yscrollbar.set)
self.textarea.grid(row=8, column=1, columnspan=4, rowspan=1,
padx=0, sticky=E + W + S + N)
def on_okay(self):
self.textarea.delete("1.0", END)
exec_path = r"\Test.py" #insert location of Test.py
self.process = subprocess.Popen([exec_path, 'var_test'], shell = True, stdout = subprocess.PIPE, stderr = subprocess.STDOUT)
self.q = Queue(maxsize = 1024)
t = Thread(target=self.reader_thread, args=[self.q])
t.daemon = True
t.start()
self.update(self.q)
def reader_thread(self, q):
try:
with self.process.stdout as pipe:
for line in iter(pipe.readline, b''):
q.put(line)
finally:
q.put(None)
def update(self, q):
for line in self.iter_except(q.get_nowait, Empty):
if line is None:
#self.quit()
return
else:
self.textarea.insert(INSERT, line)
self.textarea.yview(END)
break
self.root.after(40, self.update, q)
def iter_except(self, function, exception):
try:
while True:
yield function()
except exception:
return
def read_update(self):
while True:
line = self.process.stdout.readline()
if line == "" and self.process.poll() != None:
break
elif line == "":
pass
else:
self.textarea.insert(INSERT, line)
self.textarea.yview(END)
self.textarea.update_idletasks()
def quit(self):
try:
self.process.kill()
except AttributeError:
pass
finally:
self.root.destroy()
Test.py
import sys
from time import sleep
var = sys.argv
print var
for i in range(1, 10):
print i
print "finished printing numbers"
sleep(10)
print "finished"
谢谢你的帮助!我非常绝望,因为我已经尝试解决这个问题好几个小时了…打印后使用sys.stdout.flush()