Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

python tkinter with threading causing crash

Tags:

python

tkinter

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()
like image 656
sarbjit Avatar asked Jan 05 '13 03:01

sarbjit


1 Answers

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.

like image 97
Bryan Oakley Avatar answered Sep 18 '22 05:09

Bryan Oakley