我正在尝试在主要任务中显示来自后台任务的计数变量,这是我的tkinter GUI。为什么?我想显示长时间执行后台任务正在执行,然后使用此计数变量使用进度条可视化它。
我的问题是,即使使用Queue
,我也无法显示计数变量。也许我在理解python及其对象和/或线程的行为方面遇到了问题。
import threading
import time
import Queue
import Tkinter as Tk
import Tkconstants as TkConst
from ScrolledText import ScrolledText
from tkFont import Font
import loop_simulation as loop
def on_after_elapsed():
while True:
try:
v = dataQ.get(timeout=0.1)
except:
break
scrText.insert(TkConst.END, str(v)) # "value=%d\n" % v
scrText.see(TkConst.END)
scrText.update()
top.after(100, on_after_elapsed)
def thread_proc1():
x = -1
dataQ.put(x)
x = loop.loop_simulation().start_counting()
# th_proc = threading.Thread(target=x.start_counting())
# th_proc.start()
for i in range(5):
for j in range(20):
dataQ.put(x.get_i())
time.sleep(0.1)
# x += 1
time.sleep(0.5)
dataQ.put(x.get_i())
top = Tk.Tk()
dataQ = Queue.Queue(maxsize=0)
f = Font(family='Courier New', size=12)
scrText = ScrolledText(master=top, height=20, width=120, font=f)
scrText.pack(fill=TkConst.BOTH, side=TkConst.LEFT, padx=15, pady=15, expand=True)
th = threading.Thread(target=thread_proc1)
th.start()
top.after(100, on_after_elapsed)
top.mainloop()
th.join()
在thread_proc1()
中我想得到后台任务计数器的值。这是后台任务:
import time
class loop_simulation:
def __init__(self):
self.j = 0
# self.start_counting()
def start_counting(self):
for i in range(0, 1000000):
self.j = i
time.sleep(0.5)
def get_i(self):
return str(self.j)
答案 0 :(得分:0)
计数变量未显示的原因是
x = loop.loop_simulation().start_counting()
thread_proc1()
中的声明。这会创建一个loop_simulation
实例并调用其start_counting()
方法。但是,除了已经在-1
中插入dataQ
之外,thread_proc1()
在start_counting()
返回之前不做任何其他事情,而这不会是很长时间(500K秒)。
与此同时,您的脚本的其余部分正在运行,并且只显示放入的初始-1
。
另请注意,如果start_counting()
确实返回,则其None
的值将分配给x
,以后的代码会尝试将其用于:x.get_i()
。< / p>
下面是修复这些问题的代码的重新编写,并且更紧密地遵循PEP 8 - Style Guide for Python Code。为了避免调用start_counting()
的主要问题,我将loop_simulation
类更改为threading.Thread
的子类并将其重命名为LoopSimulation
,并在{{1}中创建它的实例因此,除了处理基于tkinter的GUI的主要线程之外,现在有两个后台线程。
thread_proc1
import loop_simulation as loop
from ScrolledText import ScrolledText
import threading
import Tkinter as Tk
import Tkconstants as TkConst
from tkFont import Font
import time
import Queue
def on_after_elapsed():
# removes all data currently in the queue and displays it in the text box
while True:
try:
v = dataQ.get_nowait()
scrText.insert(TkConst.END, str(v)+'\n')
scrText.see(TkConst.END)
except Queue.Empty:
top.after(100, on_after_elapsed)
break
def thread_proc1():
dataQ.put(-1)
ls = loop.LoopSimulation() # slow background task Thread
ls.start_counting()
while ls.is_alive(): # background task still running?
for i in range(5):
for j in range(20):
dataQ.put(ls.get_i())
time.sleep(0.1)
time.sleep(0.5)
dataQ.put('background task finished')
top = Tk.Tk()
dataQ = Queue.Queue(maxsize=0)
font = Font(family='Courier New', size=12)
scrText = ScrolledText(top, height=20, width=120, font=font)
scrText.pack(fill=TkConst.BOTH, side=TkConst.LEFT, padx=15, pady=15,
expand=TkConst.YES)
th = threading.Thread(target=thread_proc1)
th.daemon = True # OK for main to exit even if thread is still running
th.start()
top.after(100, on_after_elapsed)
top.mainloop()
模块:
loop_simulation.py