I have written a python tkinter code using threads so as the tkinter wizard updates automatically by tkinter mainloop running in the main thread and background process running in separate thread. But I noticed, that python crashes after some time when running the code. Moreover its random in nature but python crashes most of the time. I have written a small test code which can show this problem (My original code is similar to this but having some real processes and many other features, so I am sharing the test code).
###################################################################### # Test Code for Tkinter with threads import Tkinter import threading import Queue import time # Data Generator which will generate Data def GenerateData(q): for i in range(1000000): #print "Generating Some Data, Iteration %s" %(i) time.sleep(0.01) q.put("Some Data from iteration %s. Putting this data in the queue for testing" %(i)) # Queue which will be used for storing Data q = Queue.Queue() def QueueHandler(widinst, q): linecount = 0 while True: print "Running" if not q.empty(): str = q.get() linecount = linecount + 1 widinst.configure(state="normal") str = str + "n" widinst.insert("end", str) if linecount > 100: widinst.delete('1.0', '2.0') linecount = linecount - 1 widinst.see('end') widinst.configure(state="disabled") # Create a thread and run GUI & QueueHadnler in it tk = Tkinter.Tk() scrollbar = Tkinter.Scrollbar(tk) scrollbar.pack(side='right', fill='y' ) text_wid = Tkinter.Text(tk,yscrollcommand=scrollbar.set) text_wid.pack() t1 = threading.Thread(target=GenerateData, args=(q,)) t2 = threading.Thread(target=QueueHandler, args=(text_wid,q)) t2.start() t1.start() tk.mainloop() ######################################################################
TO REPRODUCE:
If you open this code in IDLE and run it, it will sometimes appeared to be in hang state. So to reproduce, modify the sleep time to 0.1 from 0.01 and run it. After this stop the application, and modify it back to 0.01, do save and run it. This time it will run and after some time, python will stop working. I am using windows 7 (64 bit).
QUESTION
I have submitted it to python bugs and it got rejected. But I got this idea from one of the stackoverflow question to use queue for writing in tkinter. Can some one please suggest what should be done to handle it.
EDITED CODE:
# Test Code for Tkinter with threads import Tkinter import threading import Queue import time # Data Generator which will generate Data def GenerateData(q): for i in range(1000000): #print "Generating Some Data, Iteration %s" %(i) time.sleep(0) q.put("Some Data from iteration %s. Putting this data in the queue for testing" %(i)) # Queue which will be used for storing Data q = Queue.Queue() def QueueHandler(): global widinst, q linecount = 0 if not q.empty(): str = q.get() linecount = linecount + 1 widinst.configure(state="normal") str = str + "n" widinst.insert("end", str) if linecount > 100: widinst.delete('1.0', '2.0') linecount = linecount - 1 widinst.see('end') widinst.configure(state="disabled") tk.after(1,QueueHandler) # Create a thread and run GUI & QueueHadnler in it tk = Tkinter.Tk() scrollbar = Tkinter.Scrollbar(tk) scrollbar.pack(side='right', fill='y' ) text_wid = Tkinter.Text(tk,yscrollcommand=scrollbar.set) text_wid.pack() t1 = threading.Thread(target=GenerateData, args=(q,)) #t2 = threading.Thread(target=QueueHandler, args=(text_wid,q)) #t2.start() widinst = text_wid t1.start() tk.after(1,QueueHandler) tk.mainloop()
Advertisement
Answer
Tkinter is not thread safe; you cannot access Tkinter widgets from anywhere but the main thread. You will need to refactor your code so that QueueHandler
runs in the main thread.