1

I'm using OSX 10.6.8, Python 2.7.2 with Tkinter version 8.5, I clean installed Python, Tkinter and IDLE yesterday cleaning up an earlier install of Python 3.2. I'm working on the "RSS Feed Filter" problem set from MIT's Open CourseWare (not for credit) and it includes several modules that I didn't write and don't understand, and one of them (the Popup class from the news_gui module) is throwing an unhandled exception that I don't know how to debug.

# 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'

The p.start() line (second from the bottom) is calling Popup from the news_gui module, here is that code:

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)

When I run with pdb enabled here is my output:

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

and then it hangs. I can tell that this has something to do with threading and Tkinter but I'm at a loss of what to do next.

Edit: Just installed Python 2.7.2 on a Windows 7 virtual machine and the problem happens there as well.

9
  • If you are using the python.org 2.7.2 64-/32-bit installer for OS X 10.6+, make sure you also install ActiveState Tcl/Tk 8.5. The Apple-supplied Tcl/Tk 8.5 in OS X 10.6 is seriously buggy (the 10.7 version is better but still has a few key bugs). See python.org/download/mac/tcltk Commented Apr 4, 2012 at 19:06
  • I believe that's the one that I installed during my Python cleanup, but is there a good way to double-check? Commented Apr 4, 2012 at 19:13
  • Look at the file /Library/Frameworks/Tcl.framework/tclConfig.sh. It should exist and contain TCL_VERSION='8.5' and TCL_PATCH_LEVEL='.11' - that's the most recent version. Also, if you have Xcode developer tools installed, try this: otool -L $(python2.7 -c "import _tkinter;print(_tkinter.__file__)") The output should include /Library/Frameworks/Tcl.framework/Versions/8.5/Tcl. Commented Apr 4, 2012 at 19:26
  • Here's what I get from dev tools: {/Library/Frameworks/Tcl.framework/Versions/8.5/Tcl (compatibility version 8.5.0, current version 8.5.9) /Library/Frameworks/Tk.framework/Versions/8.5/Tk (compatibility version 8.5.0, current version 8.5.9) /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 125.2.0)} Is the 8.5.9 a problem? Commented Apr 4, 2012 at 19:37
  • Uh-oh, looks like 8.5.9 is the Apple version, I'll get the Active State version going and see what that does for me, thanks for the help so far Commented Apr 4, 2012 at 19:39

1 Answer 1

1

I found something of a solution, though I can't speak to the overall fitness of it. It may help somebody else in a similar pickle, but if anybody more knowledgable can chime in that would be helpful, too.

I downloaded mtTkinter from http://tkinter.unpythonic.net/wiki/mtTkinter. It says "The modified code intercepts out-of-thread Tkinter calls and marshals them through a queue which is read by an 'after' event running periodically in the main loop.".

Not sure exactly how, but it fixed the problem.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.