【问题标题】:Python Tkinter Unhandled Exception In Thread Started by <function main_thread at ...>由 <function main_thread at ...> 启动的线程中的 Python Tkinter 未处理异常
【发布时间】:2012-04-04 19:02:25
【问题描述】:

我使用的是 OSX 10.6.8、Python 2.7.2 和 Tkinter 版本 8.5,我昨天清理了安装的 Python、Tkinter 和 IDLE,清理了早期安装的 Python 3.2。我正在研究麻省理工学院 Open CourseWare 中的“RSS 提要过滤器”问题集(不是为了学分),它包括几个我没有编写和不理解的模块,其中一个模块(来自 news_gui 的 Popup 类模块)正在抛出一个我不知道如何调试的未处理异常。

# 6.00 Problem Set 5
# RSS Feed Filter


import pdb
#pdb.set_trace()


import feedparser
import string
import time
from project_util import translate_html
from news_gui import Popup

#################################
########## CODE OMITTED #########
#################################

import thread

def main_thread(p):
    # A sample trigger list - you'll replace
    # this with something more configurable in Problem 11
    t1 = SubjectTrigger("Obama")
    t2 = SummaryTrigger("MIT")
    t3 = PhraseTrigger("Supreme Court")
    t4 = OrTrigger(t2, t3)
    triggerlist = [t1, t4]

    # TODO: Problem 11
    # After implementing readTriggerConfig, uncomment this line 
    #triggerlist = readTriggerConfig("triggers.txt")

    guidShown = []

    while True:
        print "Polling..."

        # Get stories from Google's Top Stories RSS news feed
        stories = process("http://news.google.com/?output=rss")
        # Get stories from Yahoo's Top Stories RSS news feed
        stories.extend(process("http://rss.news.yahoo.com/rss/topstories"))

        # Only select stories we're interested in
        stories = filter_stories(stories, triggerlist)

        # Don't print a story if we have already printed it before
        newstories = []
        for story in stories:
            if story.get_guid() not in guidShown:
                newstories.append(story)

        for story in newstories:
            guidShown.append(story.get_guid())
            p.newWindow(story)

        print "Sleeping..."
        time.sleep(SLEEPTIME)

SLEEPTIME = 60 #seconds -- how often we poll
if __name__ == '__main__':
    print '1'
    p = Popup()
    print '2'
    thread.start_new_thread(main_thread, (p,))
    print '3'
    p.start()
    print '4'

p.start() 行(倒数第二个)正在从 news_gui 模块调用 Popup,代码如下:

import Tkinter
import time

print help(Tkinter.Tk)

#root = Tk()
#root.withdraw()

import pdb


# The Popup class
class Popup:
    def __init__(self):
        print 'Popup init'

        self.root = Tkinter.Tk()
        self.root.withdraw()

        """
    self.root.mainloop()
        def drawALot():
            self.root = Tk()
            self.root.withdraw()
            self.root.mainloop()
        thread.start_new_thread(drawALot, ())
    """
    def start(self):
        print 'Popup start'
        pdb.set_trace()
        self.root.mainloop()

    def _makeTheWindow(self, item):
        """
        Private method that does the actual window drawing
        """
        print 'Popup _makeTheWindow'
        root = Tkinter.Toplevel()
        root.wm_title("News Alert")

        w = root.winfo_screenwidth()/20
        h = root.winfo_screenheight()/4

        title = Tkinter.Text(root, padx=5, pady=5, height=3, wrap=Tkinter.WORD, bg="white")
        title.tag_config("title", foreground="black", font=("helvetica", 12, "bold"))
        title.tag_config("subject", foreground="black", font=("helvetica", 12, "bold"))
        title.insert(Tkinter.INSERT, "Title: %s" % item.get_title(), "title")
        title.insert(Tkinter.INSERT, "\nSubject: ", "subject")
        title.insert(Tkinter.INSERT, item.get_subject().rstrip(), "subject")    

        title.config(state=Tkinter.DISABLED, relief = Tkinter.FLAT)
        title.grid(sticky=Tkinter.W+Tkinter.E)

        print '_makeTheWindow .5'

        summary = Tkinter.Text(root, padx=10, pady=5, height=15, wrap=Tkinter.WORD, bg="white")
        summary.tag_config("text", foreground="black", font=("helvetica", 12))
        summary.insert(Tkinter.INSERT, item.get_summary().lstrip(), "text")

        summary.config(state=Tkinter.DISABLED, relief = Tkinter.FLAT)
        summary.grid(sticky=Tkinter.W+Tkinter.E)

        link = Tkinter.Text(root, padx=5, pady=5, height=4, bg="white")
        link.tag_config("url", foreground="blue", font=("helvetica", 10, "bold"))
        link.insert(Tkinter.INSERT, item.get_link(), "url")

        link.config(state=Tkinter.DISABLED, relief=Tkinter.FLAT)
        link.grid(sticky=Tkinter.W+Tkinter.E)

        print '_makeTheWindow end'

    def newWindow(self, item):
        """
        Displays a popup with the contents of the NewsStory newsitem
        """
        print 'Popup newWindow'
        self.root.after(0, self._makeTheWindow, item)

当我在启用 pdb 的情况下运行时,这是我的输出:

None
1
Popup init
2
3Polling...

Popup start
> /Users/**********/Desktop/Learn/CS Stuffs/6-00sc-spring-2011/6-00sc-spring-2011/contents/unit-2/lecture-12-introduction-to-simulation-and-random-walks/ps5/news_gui.py(31)start()
-> self.root.mainloop()
(Pdb) s
--Call--Unhandled exception in thread started by 
<function main_thread at 0x1026ed848>>
 /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-tk/Tkinter.py(1015)mainloop()
-> def mainloop(self, n=0):
(Pdb) s
> /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-tk/Tkinter.py(1017)mainloop()
-> self.tk.mainloop(n)
(Pdb) s

然后挂起。我可以说这与线程和 Tkinter 有关,但我不知道下一步该做什么。

编辑:刚刚在 Windows 7 虚拟机上安装了 Python 2.7.2,问题也发生在那里。

【问题讨论】:

  • 如果您在 OS X 10.6+ 上使用 python.org 2.7.2 64-/32 位安装程序,请确保您还安装了 ActiveState Tcl/Tk 8.5。 Apple 提供的 OS X 10.6 中的 Tcl/Tk 8.5 存在严重错误(10.7 版本更好,但仍有一些关键错误)。见python.org/download/mac/tcltk
  • 相信这是我在 Python 清理过程中安装的那个,但是有没有好的方法来仔细检查?
  • 查看文件/Library/Frameworks/Tcl.framework/tclConfig.sh。它应该存在并包含TCL_VERSION='8.5'TCL_PATCH_LEVEL='.11' - 这是最新版本。另外,如果你安装了 Xcode 开发工具,试试这个:otool -L $(python2.7 -c "import _tkinter;print(_tkinter.__file__)") 输出应该包括/Library/Frameworks/Tcl.framework/Versions/8.5/Tcl
  • 这是我从开发工具中得到的:{/Library/Frameworks/Tcl.framework/Versions/8.5/Tcl(兼容版本 8.5.0,当前版本 8.5.9)/Library/Frameworks/Tk .framework/Versions/8.5/Tk(兼容版本8.5.0,当前版本8.5.9)/usr/lib/libSystem.B.dylib(兼容版本1.0.0,当前版本125.2.0)}就是8.5.9有问题吗?
  • 呃,哦,看起来 8.5.9 是 Apple 版本,我将启动 Active State 版本,看看它对我有什么作用,感谢到目前为止的帮助

标签: python multithreading tkinter


【解决方案1】:

我找到了一些解决方案,但我无法说出它的整体适用性。它可能会帮助其他人在类似的泡菜中,但如果有更多知识渊博的人可以参与进来,那也会有所帮助。

我从http://tkinter.unpythonic.net/wiki/mtTkinter 下载了 mtTkinter。它说“修改后的代码拦截线程外的 Tkinter 调用,并通过一个队列对它们进行编组,该队列由主循环中定期运行的 'after' 事件读取。”。

不确定具体如何,但它解决了问题。

【讨论】:

    猜你喜欢
    • 2018-12-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-25
    • 1970-01-01
    • 1970-01-01
    • 2013-02-27
    • 1970-01-01
    相关资源
    最近更新 更多