Description
I noticed that people found the "rarely create exception types" suggestion in this style guide problematic, for some very valid reasons.
There is the worry that by raising built-in types, like ValueError
and LookupError
, you could mask actual coding errors. It was suggested that it's always better to subclass these types and raise your own exception type, to make the difference clear. This was in a discussion with @ramalho and @dabeaz on Twitter.
Quite a few people brought up that the impulse for this suggestion is that a caller shouldn't need to know about 10 different exception types to catch every last well-defined error condition. It seems most agree on that. @jackdied said: "Most exceptions I see are defined once, raised once and caught once." This would indeed be bad style. Many suggested that when making many different types, you could simplify life for the caller by having a "root" error type for a given library/API, and making all special errors subclass this.
I took a look at how requests
does this. They introduce 19 exception types related to HTTP and a few of them subclass built-in exception types. Most of them also sub-class a "root" type, called RequestException
, which seems to cover library-specific errors you may choose to intentionally ignore, like InvalidURL
.
https://github.com/kennethreitz/requests/blob/master/requests/exceptions.py
I doubt that most user code should be creating exception trees like this -- HTTP can fail in a number of specific and well-known ways, and this is a library of standard library quality. It's also important to point out that even requests
chooses to keep most of these types implementation-free.
So, I wonder if I'm too harsh on exception types since Python does make it exceedingly easy to create no-impl exception classes that are instantly useful in explaining well-known errors and disambiguate them from code problems. I'll reconsider this one.