带有线程的python tkinter导致崩溃 [英] python tkinter with threading causing crash

查看:90
本文介绍了带有线程的python tkinter导致崩溃的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

复制:

如果你在 IDLE 中打开这段代码并运行它,它有时会出现在挂起状态.所以要重现,将睡眠时间从 0.01 修改为 0.1 并运行它.在这之后停止应用程序,并将其修改回 0.01,保存并运行它.这次它将运行,一段时间后,python 将停止工作.我使用的是 Windows 7(64 位).

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

问题

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

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.

编辑代码:

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

推荐答案

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

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.

这篇关于带有线程的python tkinter导致崩溃的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆