41

In Python, what's the best way to catch "all" exceptions?

except: # do stuff with sys.exc_info()[1]

except BaseException as exc:

except Exception as exc:

The catch may be executing in a thread.

My aim is to log any exception that might be thrown by normal code without masking any special Python exceptions, such as those that indicate process termination etc.

Getting a handle to the exception (such as by the clauses above that contain exc) is also desirable.

Matt Joiner
  • 112,946
  • 110
  • 377
  • 526

3 Answers3

67
  • except Exception: vs except BaseException::

    The difference between catching Exception and BaseException is that according to the exception hierarchy exception like SystemExit, KeyboardInterrupt and GeneratorExit will not be caught when using except Exception because they inherit directly from BaseException.

  • except: vs except BaseException::

    The difference between this two is mainly in python 2 (AFAIK), and it's only when using an old style class as an Exception to be raised, in this case only expression-less except clause will be able to catch the exception eg.

    class NewStyleException(Exception): pass
    
    try:
       raise NewStyleException
    except BaseException:
       print "Caught"
    
    class OldStyleException: pass
    
    try:
       raise OldStyleException
    except BaseException:
       print "BaseException caught when raising OldStyleException"
    except:
       print "Caught"
    
Eric O. Lebigot
  • 91,433
  • 48
  • 218
  • 260
mouad
  • 67,571
  • 18
  • 114
  • 106
  • 2
    I made `NewStyleException` inherit from `Exception`, as is officially recommended (http://docs.python.org/tutorial/errors.html#user-defined-exceptions). – Eric O. Lebigot Aug 24 '11 at 06:24
32

If you need to catch all exceptions and do the same stuff for all, I'll suggest you this :

try:
   #stuff
except:
   # do some stuff

If you don't want to mask "special" python exceptions, use the Exception base class

try:
   #stuff
except Exception:
   # do some stuff

for some exceptions related management, catch them explicitly :

try:
   #stuff
except FirstExceptionBaseClassYouWantToCatch as exc:
   # do some stuff
except SecondExceptionBaseClassYouWantToCatch as exc:
   # do some other stuff based
except (ThirdExceptionBaseClassYouWantToCatch, FourthExceptionBaseClassYouWantToCatch) as exc:
   # do some other stuff based

The exception hierarchy from the python docs should be a usefull reading.

Cédric Julien
  • 78,516
  • 15
  • 127
  • 132
-1

In order to avoid masking basic exceptions, you need to "re-raise" any exceptions which aren't the ones which you explicitly want to handle, e.g. (adapted from 8. Errors and Exceptions):

import sys

try: # do something that could throw an exception: except IOError as (errno, strerror): print "I/O error({0}): {1}".format(errno, strerror) except ValueError: print "Could not convert data to an integer." except: # maybe log the exception (e.g. in debug mode) # re-raise the exception: raise

Peter
  • 2,526
  • 1
  • 23
  • 32
  • 4
    The final `except: raise` does not do anything: it can be skipped altogether; non-IOError and non-ValueError exceptions are simply not caught and are automatically raised by the interpreter. – Eric O. Lebigot Aug 24 '11 at 06:20
  • 3
    @EOL You're right. I have edited my answer to indicate why the final except: might be useful. – Peter Aug 25 '11 at 14:11