4

In python is it true that except Exception as ex or except BaseException as ex is the the same as except: but you get a reference to the exception?

From what I understand BaseException is the newer default catch-all.

Aside from that why would you ever want just an except: clause?

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
atxdba
  • 5,158
  • 5
  • 24
  • 30

5 Answers5

5

The difference between the three is:

  1. bare except catches everything, including system-exiting things like KeyboardInterrupt;
  2. except Exception[ as ex] will catch any subclass of Exception, which should be all your user-defined exceptions and everything built-in that is non-system-exiting; and
  3. except BaseException[ as ex] will, like bare except, catch absolutely everything.

Generally, I would recommend using 2. (ideally as a fallback, after you have caught specific/"expected" errors), as this allows those system-exiting exceptions to percolate up to the top level. As you say, the as ex part for 2. and 3. lets you inspect the error while handling it.

There is a useful article on "the evils of except" here.

jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
5

There are several differences, apart from Pokémon exception handling* being a bad idea.

Neither except Exception: nor except BaseException: will catch old-style class exceptions (Python 2 only):

>>> class Foo(): pass
... 
>>> try:
...     raise Foo()
... except Exception:
...     print 'Caught'
... 
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
__main__.Foo: <__main__.Foo instance at 0x10ef566c8>
>>> try:
...     raise Foo()
... except BaseException:
...     print 'Caught'
... 
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
__main__.Foo: <__main__.Foo instance at 0x10ef56680>
>>> try:
...     raise Foo()
... except:
...     print 'Caught'
... 
Caught

because the old-style object is not derived from BaseException or Exception. This is a good reason to never use custom exceptions that do not derive from Exception, in any case.

Next, there are three exceptions that derive from BaseException, but not from Exception; in most cases you don't want to catch those. SystemExit, KeyboardInterrupt and GeneratorExit are not exceptions you would want to catch in the normal course of exception handling. If you use except BaseException: you do catch these, except Exception will not.


* Pokémon exception handling because you gotta catch em all.

Community
  • 1
  • 1
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
3

If you truly do not care what the reason or message of the failure was, you can use a bare except:. Sometimes this is useful if you are trying to access some functionality which may or may not be present or working, and if it fails you plan to degrade gracefully to some other code path. In that case, what the error type or string was does not affect what you're going to do.

John Zwinck
  • 239,568
  • 38
  • 324
  • 436
  • Indeed. It's basically a performance optimization. If I have an `except Exception` clause, I'm basically stating that I will always execute this block of code if an error is thrown that I haven't otherwise explicitly caught. If I know that I don't care about what that exception is, no need to waste an object alias operation to store the `Exception`. – aruisdante Mar 14 '14 at 14:44
2

It's not quite the case, no.

If you have a look at the Python documentation on built-in exceptions (specifically this bit) you see what exceptions inherit from where. If you use raw except: it will catch every exception thrown which even includes KeyboardInterrupt which you almost certainly don't want to catch; the same will happen if you catch BaseException with except BaseException as exp: since all exceptions inherit from it.

If you want to catch all program runtime exceptions it's proper to use except Exception as exp: since it won't catch the type of exceptions that you want to end the program (like KeyboardInterrupt).

Now, people will tell you it's a bad idea to catch all exceptions in this way, and generally they're right; but if for instance you have a program processing a large batch of data you may rightfully want it to not exit in case of an exception. So long as you handle the exception properly (ie, log it and make sure the user sees an exception has occurred) but never just pass; if your program produces errors you're unaware of, it will do strange things indeed!

0

Aside from that why would you ever want just an except: clause?

Short answer: You don't want that.

Longer answer: Using a bare except: takes away the ability to distinguish between exceptions, and even getting a hand on the exception object is a bit harder. So you normally always use the form except ExceptionType as e:.

glglgl
  • 89,107
  • 13
  • 149
  • 217
  • You forgot the `as` keyword there. `except ExceptionType as e:`. – Martijn Pieters Mar 14 '14 at 14:54
  • @MartijnPieters Thanks. I planned to write `except ExceptionType, e:` as I am used to, but that seems to have disappeared in 3.x. – glglgl Mar 14 '14 at 15:42
  • It has, the comma has been deprecated, Python 2.6 and up support the new syntax (see http://docs.python.org/2/whatsnew/2.6.html#pep-3110-exception-handling-changes). – Martijn Pieters Mar 14 '14 at 15:45