catch exceptions from anywhere...the canonical way?

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

No need for try: except: if you set sys.excepthook ...

  https://gitorious.org/gnumed/gnumed/source/0ca52b1240ecc3f381c305837684358cc8da9272:gnumed/gnumed/client/gnumed.py

  https://gitorious.org/gnumed/gnumed/source/0ca52b1240ecc3f381c305837684358cc8da9272:gnumed/gnumed/client/wxpython/gmGuiMain.py

  https://gitorious.org/gnumed/gnumed/source/0ca52b1240ecc3f381c305837684358cc8da9272:gnumed/gnumed/client/wxpython/gmExceptionHandlingWidgets.py

  https://gitorious.org/gnumed/gnumed/source/0ca52b1240ecc3f381c305837684358cc8da9272:gnumed/gnumed/client/pycommon/gmTools.py

Grep for sys.excepthook and similar strings.

Karsten

···

On Tue, Jan 28, 2014 at 11:32:07PM -0500, C M wrote:

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:

python - Catch MainLoop exceptions and displaying them in MessageDialogs - Stack Overflow

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?

--
GPG key ID E4071346 @ gpg-keyserver.de
E167 67FD A291 2BEA 73BD 4537 78B9 A9F9 E407 1346

Hi Che,

···

On 29 January 2014 05:32, 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), but are the answers there what people here would recommend, or some other way?

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()

-------------------------------------------------------------

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

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:

python - Catch MainLoop exceptions and displaying them in MessageDialogs - Stack Overflow

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: C++ & Python Sandwich - wxPyWiki

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

Hi Che and Robin,

wxExcept.py (2.28 KB)

···

On Thursday, January 30, 2014 8:40:18 PM UTC-6, Robin Dunn wrote:

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

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

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 (1.77 KB)

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

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 :slight_smile:

···

On 31/01/2014 15:30, 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!

Mike

--

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

Mark Lawrence

My IDE puts that into the docstring and the Python docs call it a constructor in its definition: 3. Data model — Python 2.7.18 documentation

  • Mike
···

On Friday, January 31, 2014 1:11:10 PM UTC-6, Mark Lawrence wrote:

On 31/01/2014 15:30, 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](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

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 :slight_smile:


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

Mark Lawrence

I think the docs are wrong so I've asked for clarification on the main Python mailing list/news group.

···

On 31/01/2014 19:16, Mike Driscoll wrote:

On Friday, January 31, 2014 1:11:10 PM UTC-6, Mark Lawrence wrote:

    On 31/01/2014 15:30, 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!
     >
     > Mike
     >
     > --

    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 :slight_smile:

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

    Mark Lawrence

My IDE puts that into the docstring and the Python docs call it a
constructor in its definition:
3. Data model — Python 2.7.18 documentation

- Mike

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

Mark Lawrence

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.

···

--
Robin Dunn
Software Craftsman

Robin,

wxExceptDecorator2.py (1.81 KB)

···

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](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.


Robin Dunn

Software Craftsman

http://wxPython.org

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

  • Mike

Mike Driscoll wrote:

Robin,

    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.

···

On Tuesday, February 4, 2014 8:37:06 PM UTC-6, Robin Dunn wrote:

--
Robin Dunn
Software Craftsman

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

Mike Driscoll wrote:

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.

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 (2.65 KB)

···

--
Robin Dunn
Software Craftsman

Hi Robin,

···

On Saturday, February 8, 2014 4:38:31 PM UTC-6, Robin Dunn wrote:

Mike Driscoll wrote:

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](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.

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.


Robin Dunn

Software Craftsman

http://wxPython.org

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

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
···

On Saturday, February 8, 2014 4:38:31 PM UTC-6, Robin Dunn wrote:

Mike Driscoll wrote:

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](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.

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.


Robin Dunn

Software Craftsman

http://wxPython.org

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.

···

--
Robin Dunn
Software Craftsman