You probably shouldn’t be using except: or except Exception: in Python, sometimes called ‘catch-all exceptions’ or ‘naked excepts’.

I’ve tried to find a good article or blog post discussing this, but I haven’t found any thorough discussions of the problems that arise.

Let’s take a look at exceptions. Python is excellent at throwing exceptions, and errs on the side of more exceptions rather than less. For example, this code will raise KeyError:

The equivalent code in other languages will just return a sentinel value. For example, JavaScript:

The main disadvantage of the JavaScript approach is that it’s easy to get confused when you have your sentinel value in the hashmap. It’s hard to distinguish {} from {'foobar': undefined}.

So, there are a large number of situations that will throw exceptions in Python.

Let’s consider the following piece of Django code, which fetches a page, if it exists.

This works as expected. However, can you see the mistake in this version?

This code will actually throw AttributeError, since Page.object doesn’t exist. However, since we used a catch-all except, we don’t get any error. Subtle bugs like these can be a pain to track down later.

The solution is to always name the specific exception you’re expecting. Note there’s a nasty gotcha with catching multiple exceptions:

The correct way to write this is:

To avoid this gotcha completely, you can either use the excellent Pyflakes to check your code, or use the as syntax:

As with every rule, there are a few exceptions. The first is when you’re allowing exceptions to propagate.

The other case is long running process, such as daemons:

In this case, you only want a naked except at the very top level of your program, and you want the exception to go somewhere. I like to log to Sentry or to a log file monitored by Papertrail.

To sum up: Only catch the exceptions you’re expecting to see. For all other exceptions, you want to be informed about it so you can fix it.