Interesting decorator use.

Scott David Daniels Scott.Daniels at Acm.Org
Thu Feb 24 14:15:07 EST 2005


I have started doing the following to watch for exceptions in wxPython.
I'd like any input about (A) the interface, and (B) the frame before I
throw it in the recipes book.

     import wx, os, sys
     errorframe = None

     def watcherrors(function):
         '''function decorator to display Exception information.'''
         def substitute(*args, **kwargs):
             try:
                 return function(*args, **kwargs)
             except Exception:
                 error_type, error, traceback = sys.exc_info()
                 mb = wx.MessageDialog(errorframe,
                             '%s\n\nClick OK to see traceback' % error,
                             'Error in Run',
                             wx.OK | wx.CANCEL | wx.ICON_ERROR)
                 if wx.ID_OK == mb.ShowModal():
                     mb.Destroy()
                     from traceback import extract_tb
                     trace = ['%s line %s in %s:\n\t%s' % (
                              (os.path.splitext(os.path.split(
                                  name)[1])[0], line, fun, text)
                              for name, line, fun, text in
                                  extract_tb(traceback)]
                     mb = wx.MessageDialog(errorframe,
                             '\n'.join(['%s\n' % error] + trace),
                             'Run Error w/ Traceback',
                             wx.OK | wx.ICON_ERROR)
                     result = mb.ShowModal()
                 mb.Destroy()
                 raise
         if function.__doc__ is not None:
             substitute.__doc__ = function.__doc__
         return substitute

You can use it as follows to wrap functions and methods:

     @watcherrors
     def something(somearg)
         if somearg is not None:
                 raise ValueError(somearg)


You can use this by simply placing '@watcherrors' on the line before a
function or method definition.  Some of my questions are:
    A) Is there a better name? Perhaps "exceptions" or "watcher"?
    B) Is a global the right way to define the parent of the driven
       message box, or adding another wrapper layer as follows better?

       def exceptionwatcher(base, name):
           def watcherrors(....
               ...
               def substitute(*args, **kwargs):
                 try:
                     return function(*args, **kwargs)
                 except Exception:
                     error_type, error, traceback = sys.exc_info()
                     errorframe = getattr(base, name, None) ### new code
                     ...
           return watcherrors

       Wrapping the code this way allows you to say, watcher-by-watcher,
       where to get the parent for the message box.  You would then use
       it as follows:

         @exceptionwatcher(someholder, 'frame')
         def something(somearg)
             if somearg is not None:
                     raise ValueError(somearg)

     C) Stuff I've not even thought of.

--Scott David Daniels
Scott.Daniels at Acm.Org



More information about the Python-list mailing list