我正在为一个Python模拟器创建GUI。GUI提供了设置模拟和运行模拟的工具。在模拟运行时,我想向GUI传递进度信息,并在我的simulation_frame中显示在Label上。由于需要使用多进程来运行模拟,我使用Queue将更新后的信息传递回GUI。
我的设置方式是,运行模拟会阻塞Tk主循环,因为我需要能够在调用结束时关闭我的Pool。我调用update_idletasks()来强制GUI更新进度信息。
这对我来说似乎是一种不优雅且潜在风险的解决方案。此外,虽然它在Ubuntu上运行良好,但在Windows XP上似乎无法正常工作--窗口在运行一秒钟左右后变为空白。我可以通过调用update()而不是update_idletasks()来使其在Windows中工作,但这对我来说甚至更糟糕。
有更好的解决方案吗?
相关代码:
我的设置方式是,运行模拟会阻塞Tk主循环,因为我需要能够在调用结束时关闭我的Pool。我调用update_idletasks()来强制GUI更新进度信息。
这对我来说似乎是一种不优雅且潜在风险的解决方案。此外,虽然它在Ubuntu上运行良好,但在Windows XP上似乎无法正常工作--窗口在运行一秒钟左右后变为空白。我可以通过调用update()而不是update_idletasks()来使其在Windows中工作,但这对我来说甚至更糟糕。
有更好的解决方案吗?
相关代码:
sims = []
queues = []
svars = []
names = []
i = 0
manager = mp.Manager()
for config in self.configs:
name, file, num = config.get()
j = 0
for _ in range(num):
#progress monitor label
q = manager.Queue()
s_var = StringVar()
label = Label(self.sim_frame, textvariable = s_var, bg = "white")
s_var.set("%d: Not Started"%i)
label.grid(row = i, column = 0, sticky = W+N)
self.sim_labels.append(label)
queues.append(q)
svars.append(s_var)
names.append("%s-%d"%(name, j))
sims.append(("%s-%d"%(name, j),file, data, verbose, q))
i += 1
j += 1
self.update()
# The progress tracking is pretty hacky.
pool = mp.Pool(parallel)
num_sims = len(sims)
#start simulating
tracker = pool.map_async(run_1_sim,sims)
while not tracker.ready():
pass
for i in range(num_sims):
q = queues[i]
try:
gen = q.get(timeout = .001)
# if the sim has updated, update the label
#print gen
svars[i].set(gen)
self.update()
except Empty:
pass
# The results of the map, if necessary
tracker.get()
def update(self):
"""
Redraws everything
"""
self.master.update_idletasks()
def run_1_sim(args):
"""
Runs one simulation with the specified args, output updates to the supplied
pipe every generation
"""
name,config,data, verbose, q = args
sim = Simulation(config, name=name, data = data)
generation = 0
q.put(sim.name + ": 0")
try:
while sim.run(verbose=verbose, log=True, generations = sim_step):
generation += sim_step
q.put(sim.name + ": " + str(generation))
except Exception as err:
print err