I wrote a little exception hook for pygtk applications. When an exception occurs
it will show a dialog with a full stack trace obtained using cgitb.
import gtk, gobject
import sys
_ = lambda s: s
def scrolled(widget, shadow=gtk.SHADOW_NONE):
window = gtk.ScrolledWindow()
window.set_shadow_type(shadow)
window.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
if widget.set_scroll_adjustments(window.get_hadjustment(),
window.get_vadjustment()):
window.add(widget)
else:
window.add_with_viewport(widget)
return window
class ExceptionDialog(gtk.MessageDialog):
def __init__(self, etype, evalue, etb):
gtk.MessageDialog.__init__(self, buttons=gtk.BUTTONS_CLOSE, type=gtk.MESSAGE_ERROR)
self.set_resizable(True)
self.set_markup(_("An error has occured:\n%r\nYou should save "
"your work and restart the application. If the error "
"occurs again please report it to the developer." % evalue))
import cgitb
text = cgitb.text((etype, evalue, etb), 5)
expander = gtk.Expander(_("Exception Details"))
self.vbox.pack_start(expander)
textview = gtk.TextView()
textview.get_buffer().set_text(text)
expander.add(scrolled(textview))
self.show_all()
def install_exception_hook(dialog=ExceptionDialog):
old_hook = sys.excepthook
def new_hook(etype, evalue, etb):
if etype not in (KeyboardInterrupt, SystemExit):
d = dialog(etype, evalue, etb)
d.run()
d.destroy()
old_hook(etype, evalue, etb)
new_hook.old_hook = old_hook
sys.excepthook = new_hook
if __name__ == "__main__":
install_exception_hook()
gobject.idle_add(lambda: 1/0)
gobject.idle_add(gtk.main_quit)
gtk.main()