catch exceptions from anywhere...the canonical way?

210 views
Skip to first unread message

C M

unread,
Jan 28, 2014, 11:32:07 PM1/28/14
to wxPytho...@googlegroups.com
Hi list,

At some point I'm meaning to set things up so that any unhandled exception, anywhere in the whole application (from lurking bugs) will result in a "Whoops!" dialog for the user instead of the app just hanging there or crashing.  I looked around and found this SE question and answer about it:

http://stackoverflow.com/questions/408810/catch-mainloop-exceptions-and-displaying-them-in-messagedialogs?lq=1

I'm wondering what the "canonical" answer is to this.  I guess it isn't sufficient to just wrap the app.MainLoop() in a try/except block (one person there said this doesn't even work), but are the answers there what people here would recommend, or some other way?

Thanks,
Che

Karsten Hilbert

unread,
Jan 29, 2014, 5:52:25 AM1/29/14
to wxPytho...@googlegroups.com

Andrea Gavana

unread,
Jan 29, 2014, 6:01:28 AM1/29/14
to wxPython-users
Hi Che,


The way I normally handle this is by redirecting `sys.excepthook` to some custom class, like this more or less:

sys.excepthook = MyExceptionHook

def ExceptionHook(exctype, value, trace):
    """
    Handler for all unhandled exceptions.

    :param `etype`: the exception type (`SyntaxError`, `ZeroDivisionError`, etc...);
    :type `etype`: `Exception`
    :param string `value`: the exception error message;
    :param string `trace`: the traceback header, if any (otherwise, it prints the
     standard Python header: ``Traceback (most recent call last)``.
    """

    frame = wx.GetApp().GetTopWindow()

    # Format the traceback message in whatever way you like...
    ftrace = FormatTraceback(exctype, value, trace)

    # Ensure that error gets raised to console as well
    print ftrace

    dlg = ErrorDialogShowingMessage(ftrace)


Hope this helps...

Andrea.

"Imagination Is The Only Weapon In The War Against Reality."
http://www.infinity77.net

# ------------------------------------------------------------- #
def ask_mailing_list_support(email):

    if mention_platform_and_version() and include_sample_app():
        send_message(email)
    else:
        install_malware()
        erase_hard_drives()
# ------------------------------------------------------------- #

C M

unread,
Jan 29, 2014, 12:11:21 PM1/29/14
to wxpytho...@googlegroups.com
Hi Andrea and Karsten,

Well, it's looking like sys.excepthook is indeed the winner!  Great, that's very helpful to know there seems to be a consensus (as well as on the SO answers).  I'll get to implementing something like this.

Thanks,
Che


Robin Dunn

unread,
Jan 30, 2014, 9:40:18 PM1/30/14
to wxpytho...@googlegroups.com
C M wrote:
> Hi list,
>
> At some point I'm meaning to set things up so that any unhandled
> exception, anywhere in the whole application (from lurking bugs) will
> result in a "Whoops!" dialog for the user instead of the app just
> hanging there or crashing. I looked around and found this SE question
> and answer about it:
>
> http://stackoverflow.com/questions/408810/catch-mainloop-exceptions-and-displaying-them-in-messagedialogs?lq=1
>
> I'm wondering what the "canonical" answer is to this. I guess it isn't
> sufficient to just wrap the app.MainLoop() in a try/except block (one
> person there said this doesn't even work),

There is a little more info here as to why wrapping MainLoop() in a
try/except does not work: http://wiki.wxpython.org/CppAndPythonSandwich

It would be nice if somebody could update that page with info and
examples of using sys.excepthook. Also the current solution on that
page would be handy as a decorator, so examples for using it that way
would be helpful.

--
Robin Dunn
Software Craftsman
http://wxPython.org

Mike Driscoll

unread,
Jan 31, 2014, 10:04:44 AM1/31/14
to wxpytho...@googlegroups.com
Hi Che and Robin,

I came up with an example using the sys.excepthook method (attached). Can anyone take a look and see if that's a good example and/or suggest improvements?

The code for the current solution is incomplete as it doesn't have the actual logging code in it, but I'm going to take a crack at it anyway.

- Mike
wxExcept.py

Mike Driscoll

unread,
Jan 31, 2014, 10:30:29 AM1/31/14
to wxpytho...@googlegroups.com
Hi Robin,

 

It would be nice if somebody could update that page with info and
examples of using sys.excepthook.  Also the current solution on that
page would be handy as a decorator, so examples for using it that way
would be helpful.

--
Robin Dunn
Software Craftsman
http://wxPython.org

I think I figured out how to create a class decorator out of that sample code. I have attached my example. Could you take a look and see if it's a good example? Thanks!

Mike
wxExceptDecorator.py

Mike Driscoll

unread,
Jan 31, 2014, 10:31:41 AM1/31/14
to wxpytho...@googlegroups.com
Robin,



There is a little more info here as to why wrapping MainLoop() in a
try/except does not work:  http://wiki.wxpython.org/CppAndPythonSandwich

It would be nice if somebody could update that page with info and
examples of using sys.excepthook.  Also the current solution on that
page would be handy as a decorator, so examples for using it that way
would be helpful.

--
Robin Dunn
Software Craftsman
http://wxPython.org


One other thing I forgot to mention. When we do get these examples figured out, I think they should go on the wiki page you mentioned and also on their own page to make them easier to find.

- Mike

Mark Lawrence

unread,
Jan 31, 2014, 2:11:10 PM1/31/14
to wxpytho...@lists.wxwidgets.org
> --

One minor nitpick that's now driving me nuts (I don't yet know enough
about wxPython to make other comments). Please label __new__ as the
constructor and __init__ as the initialiser as the latter is *NOT* a
constructor :)

--
My fellow Pythonistas, ask not what our language can do for you, ask
what you can do for our language.

Mark Lawrence

Mike Driscoll

unread,
Jan 31, 2014, 2:16:34 PM1/31/14
to wxpytho...@googlegroups.com, wxpytho...@lists.wxwidgets.org, bream...@yahoo.co.uk


My IDE puts that into the docstring and the Python docs call it a constructor in its definition: http://docs.python.org/2/reference/datamodel.html#object.__init__

- Mike
 

Mark Lawrence

unread,
Jan 31, 2014, 2:43:41 PM1/31/14
to wxpytho...@lists.wxwidgets.org
I think the docs are wrong so I've asked for clarification on the main
Python mailing list/news group.

Robin Dunn

unread,
Feb 4, 2014, 9:37:06 PM2/4/14
to wxpytho...@googlegroups.com
It would be nice to be able to use the decorator on things besides event
handlers, so making it more generic (with *args, **kw) would be good.

Mike Driscoll

unread,
Feb 5, 2014, 12:14:55 PM2/5/14
to wxpytho...@googlegroups.com
Robin,

I modified it a bit to use the *a, **kw format. Hopefully the attached will suffice. It worked on my machine anyway.

- Mike
wxExceptDecorator2.py

Robin Dunn

unread,
Feb 7, 2014, 4:10:48 PM2/7/14
to wxpytho...@googlegroups.com
Mike Driscoll wrote:
> Robin,
>
> On Tuesday, February 4, 2014 8:37:06 PM UTC-6, Robin Dunn wrote:
>
> Mike Driscoll wrote:
> > Hi Robin,
> >
> >
> > It would be nice if somebody could update that page with info and
> > examples of using sys.excepthook. Also the current solution on that
> > page would be handy as a decorator, so examples for using it that
> way
> > would be helpful.
> >
> > --
> > Robin Dunn
> > Software Craftsman
> > http://wxPython.org
> >
> >
> > I think I figured out how to create a class decorator out of that
> sample
> > code. I have attached my example. Could you take a look and see
> if it's
> > a good example? Thanks!
>
> It would be nice to be able to use the decorator on things besides
> event
> handlers, so making it more generic (with *args, **kw) would be good.

>
> I modified it a bit to use the *a, **kw format. Hopefully the attached
> will suffice. It worked on my machine anyway.

The self being passed to the event handler is the ExceptionLogging
instance, not the Panel instance. ISTR that there is a simple way
around this but I don't remember details at the moment.

Mike Driscoll

unread,
Feb 7, 2014, 4:28:00 PM2/7/14
to wxpytho...@googlegroups.com
Robin,



The self being passed to the event handler is the ExceptionLogging
instance, not the Panel instance.  ISTR that there is a simple way
around this but I don't remember details at the moment.


--
Robin Dunn
Software Craftsman
http://wxPython.org

Hmmm...I think that might be a bit beyond me at the moment. I can't find any examples that are similar to what you're talking about anyway.

Mike


Robin Dunn

unread,
Feb 8, 2014, 5:38:31 PM2/8/14
to wxpytho...@googlegroups.com
I don't think that this is what I was trying to remember earlier, but
implementing the decorator as a function wrapper instead of a class with
__call__ appears to do the right thing. In the attached there are two
decorator functions, one which logs to the root logger by default, and
another that wraps the first and allows the target logger name to be set.
wxExceptDecorator3.py

Mike Driscoll

unread,
Mar 14, 2014, 4:24:22 PM3/14/14
to wxpytho...@googlegroups.com
Hi Robin,

I was just thinking I would add your decorator to the wiki page, but I noticed that the C++ and Python Sandwich  page is immutable. So I'm going to blog about it instead.

- Mike

Mike Driscoll

unread,
Mar 14, 2014, 4:40:01 PM3/14/14
to wxpytho...@googlegroups.com

By the way, couldn't you have used @functools.wrap to retain the original function's name and docstring instead of setting them explicitly?

- Mike

Robin Dunn

unread,
Mar 15, 2014, 12:54:11 AM3/15/14
to wxpytho...@googlegroups.com
Mike Driscoll wrote:
>

> By the way, couldn't you have used @functools.wrap to retain the
> original function's name and docstring instead of setting them explicitly?

Yeah, I always forget about that.

> I was just thinking I would add your decorator to the wiki page, but I noticed that the C++ and Python Sandwich page is immutable. So I'm going to blog about it instead.

The wiki was getting hit hard with spam so I had to disable editing
until I can get it updated to the newest version which I hope will have
better spam blocks.
Reply all
Reply to author
Forward
0 new messages