If I run the following code from a terminal, I get a helpful error message in the terminal:
import Tkinter as tk
master = tk.Tk()
def callback():
raise UserWarning("Exception!")
b = tk.Button(master, text="This will raise an exception", command=callback)
b.pack()
tk.mainloop()
However, if I run it without a terminal (say, by double-clicking an icon), the error message is suppressed.
In my real, more complicated Tkinter application, I like that the GUI is a little crash-resistant. I don't like that my users have a hard time giving me useful feedback to fix the resulting unexpected behavior.
How should I handle this? Is there a standard way to expose tracebacks or stderror or whatnot in a Tkinter application? I'm looking for something more elegant than putting try/except everywhere.
EDIT: Jochen Ritzel gave an excellent answer below that pops up a warning box, and mentioned attaching it to a class. Just to make this explicit:
import Tkinter as tk
import traceback, tkMessageBox
class App:
def __init__(self, master):
master.report_callback_exception = self.report_callback_exception
self.frame = tk.Frame(master)
self.frame.pack()
b = tk.Button(
self.frame, text="This will cause an exception",
command=self.cause_exception)
b.pack()
def cause_exception(self):
a = []
a.a = 0 #A traceback makes this easy to catch and fix
def report_callback_exception(self, *args):
err = traceback.format_exception(*args)
tkMessageBox.showerror('Exception', err)
root = tk.Tk()
app = App(root)
root.mainloop()
My remaining confusion: Jochen mentions the possibility of having different exception reporting functions in different frames. I don't yet see how to do that. Is this obvious?
There is report_callback_exception
to do this:
import traceback
import tkMessageBox # py3: import tkinter.messagebox as tkMessageBox
# You would normally put that on the App class
def show_error(self, *args):
err = traceback.format_exception(*args)
tkMessageBox.showerror('Exception',err)
# but this works too
tk.Tk.report_callback_exception = show_error
If you didn't import Tkinter as tk
, then do
Tkinter.Tk.report_callback_exception = show_error