我正在尝试使用Tkinter和线程机制。任何人都可以解释为什么这会引发异常:
<class '_tkinter.TclError'> out of stack space (infinite loop?)
我该如何解决这个问题?下面是代码。顺便说一句,我知道有些人建议使用线程模块而不是线程,但是现在我想使用更简单的线程模块来介绍自己的机制。
from Tkinter import *
import thread
import time
def main_thread(master):
try:
frame = Frame(master)
frame.pack(side='bottom')
scrollbar = Scrollbar(master)
scrollbar.pack(side='right',fill='y')
t = "Title"
title = StringVar()
title.set(t)
ttl = Label(master, textvariable=title, font=("Helvetica", 18))
ttl.pack(side='top')
cont = Text(master, font=("Helvetica",14), yscrollcommand=scrollbar.set)
cont.pack(side='bottom')
button = Button(frame,text="Exit", command=root.destroy)
button.pack(side='bottom')
n = 0
while 1:
n += 1
cont.insert('end', str(n)+"\n")
time.sleep(1)
except Exception as e:
print type(e), e
if __name__ == '__main__':
root = Tk()
root.title("My counting application")
thread.start_new_thread(main_thread, (root,)) # FIXME: out of stack space (infinite loop?)
root.mainloop()
谢谢你, 卢卡
修改
我解决了替换
n = 0
while 1:
n += 1
cont.insert('end', str(n)+"\n")
time.sleep(1)
与
n = 0
def do_every_second(n):
cont.insert("end", str(n) + "\n")
n += 1
master.after(1000, do_every_second, n)
do_every_second(n)
并致电
main_thread(root)
而不是
thread.start_new_thread(main_thread, (root,))
答案 0 :(得分:4)
您的代码中存在一些致命缺陷。首先,您无法编写从多个线程触及tkinter小部件的代码。您正在主线程中创建根窗口,因此您只能直接从主线程访问窗口小部件。 Tkinter不是线程安全的。
第二个问题是你有一个无限循环,不断附加到文本小部件。它别无选择,只能最终耗尽内存。
要解决您的问题,您应该:
如果你想每秒运行一次函数,那么有比使用线程更好的方法。简而言之:
def do_every_second():
cont.insert("end", str(n) + "\n")
root.after(1000, do_every_second)
这将导致do_every_second做它做的任何事情,然后安排自己在将来一秒钟再次被调用。
答案 1 :(得分:-1)
错误是正确的 - 在tkinter
个元素之一上存在无限循环。 thread
模块与它无关。导致错误的特定行:
cont.insert('end', str(n)+"\n")
由于cont
是一个tkinter元素,因此无法在无限循环中运行它。要做你想做的事,你需要打印到控制台。如果用简单的替换违规行,可以证明这一点:
print(str(n)+"\n")
编辑:如果您真的希望达到原先预期的相同效果,this post会处理潜在的替代方案。
Edit2:我认为异常是tkinter
库的设计选择(虽然我不是专家)。这是有道理的,因为tkinter
已经为其事件循环使用了无限循环。我认为无限循环会阻止tkinter
将更改绘制到屏幕上,而是库作者选择抛出异常。 print
应该有效,因为没有什么新东西可以绘制,加上它自己的线程允许tkinter
的事件循环继续。< / p>