python tkinter与线程导致崩溃

时间:2013-01-05 03:45:08

标签: python tkinter

我已经使用线程编写了一个python tkinter代码,以便tkinter向导通过在主线程中运行的tkinter mainloop和在单独线程中运行的后台进程自动更新。但是我注意到,运行代码后python崩溃了一段时间。此外它本质上是随机的,但python在大多数时间都会崩溃。我写了一个小的测试代码,可以显示这个问题(我的原始代码与此类似,但有一些实际的进程和许多其他功能,所以我分享测试代码)。

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

重播:

如果您在IDLE中打开此代码并运行它,它有时会显示处于挂起状态。因此要重现,将睡眠时间从0.01修改为0.1并运行它。在此之后停止应用程序,并将其修改回0.01,执行保存并运行它。这次它会运行,经过一段时间后,python将停止工作。我正在使用Windows 7(64位)。

问题

我已将它提交给python错误并被拒绝。但是我从stackoverflow问题之一得到了这个想法,以便在tkinter中使用队列进行写入。有人可以建议应该采取什么措施来处理它。

编辑代码:

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

3 个答案:

答案 0 :(得分:6)

Tkinter不是线程安全的;除了主线程之外,你无法从任何地方访问Tkinter小部件。您需要重构代码,以便QueueHandler在主线程中运行。

答案 1 :(得分:4)

正如布莱恩所说,Tkinter不是线程安全的。这是一个尝试如此改进的修改:http://tkinter.unpythonic.net/wiki/mtTkinter

答案 2 :(得分:0)

Tkinter is designed to be thread-safe但不是2.x3.x中的错误。

在发布修补程序之前(以及旧版本),您应该使用mtTkinter(设计为替代版本)作为解决方法。