Catching exceptions in Tkinter's mainloop

Richard Townsend NOstarfighterSPAM at freeuk.com
Sat Mar 17 11:37:01 EST 2001


"Mike Callahan" <mcalla at home.com> wrote in message
news:%dws6.9947$Q47.2723350 at news1.rdc1.tn.home.com...
> I want to make sure that if any exception pops up inside a mainloop, that
> exception is printed to a log file and the mainloop quits. I tried to
> simulate this with the following code but failed:
>
> from Tkinter import *
>
> class Gui:
>     def __init__(self, master):
>         self.master = master
>         self.button = Button(master, text='Crash', command=self.crash)
>         self.button.pack()
>
>     def crash(self):
>         z = zz  # trigger exception
>
> root = Tk()
> app = Gui(root)
> try:
>     root.mainloop()
> except:
>     print 'caught'
>     root.quit()
>
> It doesn't work. The exception is printed out by standard traceback and
the
> mainloop continues. What am I doing wrong?
>
> Mike Callahan
>

Tkinter catches exceptions raised in callbacks and Tk by using the class
'CallWrapper' (defined in Tkinter.py). I copied the technique used by Pmw,
and created my own CallWrapper class (based on Tkinter.CallWrapper) and then
after initialising Tk, I use the following statement:

    Tkinter.CallWrapper = MyCallWrapper

MyCallWrapper's __call__ method invokes my error logging function in the
final except clause, you could get yours to print info to your log file and
quit.

Note, you must always have an except clause for SystemExit (like
Tkinter.CallWrapper does) otherwise calling sys.exit() in a callback won't
work!

e.g.

class MyCallWrapper:
    """Internal class. Stores function to call when some user
    defined Tcl function is called e.g. after an event occurred."""
    def __init__(self, func, subst, widget):
        """Store FUNC, SUBST and WIDGET as members."""
        self.func = func
        self.subst = subst
        self.widget = widget
    def __call__(self, *args):
        """Apply first function SUBST to arguments, than FUNC."""
        try:
            if self.subst:
                args = apply(self.subst, args)
            return apply(self.func, args)
        except SystemExit, msg:
            raise SystemExit, msg
        except:
            # substitute your functionality here...

Richard







More information about the Python-list mailing list