Reputation: 261
There is a simple scenario that I seem to encounter quite often: I invoke a function that can raise any number of exceptions. I won't do anything different if it is one exception versus another, I just want to log the exception information and either re-raise the exception or indicate in some other way that something didn't go as planned (such as returning None), otherwise proceed normally. So I use some form of the exception handling shown below.
Please note:
Imagine his code is running in a daemon that processes messages, so it needs to keep running, even if one of the messages causes some kind of exception.
I am aware that there is a rule of thumb that it is not generally advisable to catch a generic Exception because that may hide specfic errors that should be handled differently. (This is true in other languages as well.) This case is different because I don't care what exception is raised, the handling is the same.
Is there a better way?
def my_func(p1):
retval = None
try:
valx = other_func1(p1)
except Exception as ex:
log.error('other_func1 failed. {}: {}'.format(type(ex).__name__, ex))
else:
retval = ...
return retval
Upvotes: 4
Views: 1811
Reputation: 160437
Is there a better way?
Doubt it, Python has these built-in Base Exception Classes so creating something on your own is really just being redundant. If you handle everything in the same way, generalizing in your except
with Exception
is most likely the best way to tackle this.
Small caveat here: Exception
isn't the most general you can get, from the documentation:
All built-in, non-system-exiting exceptions are derived from this class. All user-defined exceptions should also be derived from this class.
So, it won't catch all exceptions:
In [4]: try:
...: raise SystemExit
...: except Exception as b:
...: print("Catch All")
To exit: use 'exit', 'quit', or Ctrl-D.
An exception has occurred, use %tb to see the full traceback.
SystemExit
Which, do note, is of course something you should want. A SystemExit
should exit. But, if some edge case requires it, to also catch system-exiting exceptions you can use BaseException
which is as loose as you can get with exception matching:
In [2]: try:
...: raise SystemExit
...: except BaseException as b:
...: print("Catch All")
Catch All
Use it at your own discretion but, it probably makes zero sense to actually use it, and this case does not seem to require it. I just mentioned it because it is the most general you can get. I believe the way you have done it is more than sufficient.
Upvotes: 2
Reputation: 1774
That looks like a fine way to catch them if you're handling them all the same way. If you want to check what kind of exception was raised, you can use the built-in function type
and compare the result to an exception class (for example, one from the list of built-in exception types):
try:
f()
except Exception as ex:
if type(ex)==ValueError:
handle_valueerror()
else:
handle_other_exception()
If you're handling them differently, use except <SpecificExceptionClass>
. I'm not sure what I was thinking before.
Upvotes: -1