Tkinter and thread. from stack space (infinite loop?)

I am experimenting with Tkinter and the thread mechanism. Can someone explain why this throws an exception:

<class '_tkinter.TclError'> out of stack space (infinite loop?) 

and how can i solve this? Below is the code. By the way, I know that some people suggest using a stream module instead of a stream, but now I would like to use a stream module, which is easier to just imagine a mechanism.

 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() 

Thanks, Luke


EDIT

I decided to replace

  n = 0 while 1: n += 1 cont.insert('end', str(n)+"\n") time.sleep(1) 

with

  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) 

and challenge

 main_thread(root) 

instead

 thread.start_new_thread(main_thread, (root,)) 
+6
source share
2 answers

You have a couple of fatal flaws in the code. Firstly, you simply cannot write code affecting tkinter widgets from multiple threads. You create a root window in the main thread, so that you can only access widgets from the main thread. Tkinter is not thread safe.

The second problem is that you have an infinite loop that is constantly being added to the text widget. He has no choice but to run out of memory in the end.

To solve your problem, you should:

  • does not have an infinite loop that is forever added to the text widget
  • do not access widgets from more than one thread

If you want to run a function once per second, there are better ways to do this than with threads. Shortly speaking:

 def do_every_second(): cont.insert("end", str(n) + "\n") root.after(1000, do_every_second) 

This will cause do_every_second to do everything it does, and then arrange for itself to repeat for one second in the future.

+4
source

The error is correct - there is an infinite loop on one of the tkinter elements. The thread module has nothing to do with this. The specific line causing the error:

 cont.insert('end', str(n)+"\n") 

Since cont is a cont element, you cannot start it in your infinite while loop. To do what you want, you will need to type on the console. This can be demonstrated if you replace the broken line with a simple one:

 print(str(n)+"\n") 

Edit: if you really want to achieve the same effect that you originally planned, this post has a potential alternative.

Edit2: I would suggest that the exception is the design choice by the tkinter library (although I'm not an expert). This makes sense since tkinter already uses an infinite loop for its event loop. I would suggest that an infinite loop would prevent tkinter from drawing changes on the screen, and instead library authors would rather throw an exception. A print should work, since there is nothing new to draw, plus it has its own stream that allows you to continue the tkinter event tkinter .

-1
source

All Articles