[英]Unable to terminate a python program
正如这里建议的那样,我为Tkinter创建了一个单独的类。 主要功能只是从Tkinter GUI获取比例值。 尽管我能够获得这些比例值,但是在关闭GUI后无法退出程序。 我的程序似乎在self.root.mainloop()
之后卡住了,即执行了print "mainloop"
。 如果执行以下操作(即,如果我不访问output_q
值),则终止脚本没有任何问题。
i = 0
while app.run:
print i
i = i+1
整个代码如下
from Tkinter import *
import threading, time, sys, Queue
class App(threading.Thread):
def __init__(self, var):
threading.Thread.__init__(self)
self.output_q = Queue.Queue()
self.start()
def callback(self):
self.run = 0
self.root.quit()
self.root.destroy()
def pub_y(self, val_y):
self.x_val = float(self.y_scale.get())
self.output_q.put((self.x_val, 2, 3))
def run(self):
self.root = Tk()
self.root.protocol("WM_DELETE_WINDOW", self.callback)
self.y_var = DoubleVar()
self.y_scale = Scale( self.root, from_=0, to=1, length=300, label="yaw", resolution=0.0000000000001, variable = self.y_var, orient=HORIZONTAL, command=self.pub_y)
self.y_scale.set(0.5)
self.y_scale.pack(anchor=CENTER)
label = Label(self.root, text="Hello World")
label.pack()
self.root.mainloop()
print "mainloop"
var = 1
input = Queue.Queue()
input.put((1,2,3))
app = App(input)
i = 0
while app.run:
result = app.output_q.get()
print result[0]
sys.exit(0)
有人可以指出我可能会出问题的地方吗? 谢谢!
有关代码的许多事情令人困惑,但实际上并不是错误,例如您用值为0的instance属性遮盖run
方法的事实。
您实际上是从后台线程使用tkinter的事实是错误的,并且可能导致某些平台挂起。 但这可能不是这里的原因。
您的实际问题是队列逻辑。 考虑一下它是如何工作的:
output_q.get()
,该线程将永远阻塞,直到某些东西进入队列。 run = 0
并退出。 run
现在是错误的,因此它将永远不会退出。 解决此问题的一种方法是使用您已经用于唤醒主线程的相同队列,以便可以看到您已退出:
def callback(self):
self.run = 0
self.root.quit()
self.root.destroy()
self.output_q.put(None)
当然,现在您不能只使用result[0]
,因为result
可能是None
,所以您需要添加:
if result is not None:
但是仍然存在一个问题:在一个线程中更改的变量可以保证最终对其他线程可见,但不是立即可见。 如果主线程直到它再次阻塞队列后才看到更改,该怎么办? 它永远卡住了。
我很确定这可以在CPython上运行,但是不能保证,它只是偶然发生,而且可能不适用于Jython等其他实现。 解决此问题的正确方法是使用“ Lock
或“ Condition
或“ Queue
或其他同步对象来同步对要在线程之间共享的任何变量的所有访问。
但是请注意,您实际上并不需要 while app.run:
测试了,因为您可以这样做:
while True:
result = app.output_q.get()
if result is None:
break
print result[0]
然后,您不必担心种族。 这样,您的代码更简单,并保证正确。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.