无法终止python程序
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了无法终止python程序相关的知识,希望对你有一定的参考价值。
正如here所建议的,我创建了一个独立的类,专门用于Tkinter。 main函数只从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的实例属性来影响你的run
方法的事实......
您从后台线程使用tkinter的事实实际上是错误的,并且可能导致在某些平台上挂起。但这可能不是原因。
您的实际问题是队列逻辑。想想它是如何工作的:
- 您的主线程检查线程是否正在运行。
- 你的主线程调用
output_q.get()
,它永远阻塞,直到有东西被放入队列。 - 你的后台线程获得了一个destroy事件。
- 你的后台线程设置
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]
然后你不必担心比赛。通过这种方式,您的代码更简单,并且保证正确。
以上是关于无法终止python程序的主要内容,如果未能解决你的问题,请参考以下文章