3

Python offers an extensive list of built-in exceptions.

It appears to me that most of the built-in exceptions are intended to be raised only by the interpreter or by Python's built-in functions.

So, which of these built-in exceptions should be raised in user code? Does the guidance differ between Python 2.7 and 3.x?

Coming from .NET, I believed this to be an important question. For .NET, Microsoft provides explicit guidance for what exceptions to throw and not to throw in Using Standard Exception Types.

For Python, it seems to me intuitively and from examples that I have seen that the following built-in exceptions would be appropriate to raise in user code:

IndexError
LookupError
NotImplementedError
TypeError
ValueError

...but these would not as each indicates a type of system failure:

ArithmeticError
    FloatingPointError
    OverflowError
    ZeroDivisionError
MemoryError
OSError
6
  • 2
    Do you ask for opinions or stats? Besides the very link you provide says: "User code can raise built-in exceptions. This can be used to test an exception handler or to report an error condition “just like” the situation in which the interpreter raises the same exception; [...]". It just makes sense, that those used by the intepreter are there, because they are needed anyways. I really have troubles finding the goal of this question. The only sense is to run some grep or something on some large projects. Commented Feb 3, 2015 at 15:32
  • Not adding this as an answer since it's just my opinion, but other than possibly DeprecationWarning I would just stick to subclassing Exception with your own custom exceptions (it's only two lines of code, after all) Commented Feb 3, 2015 at 15:33
  • @luk32: Please see my edit and my motivation for asking. I did not intend this question to be opinion-based. Commented Feb 3, 2015 at 16:06
  • @Moritz: Your answer could potentially lead to another question: "When should I define my own exception type instead of using a built-in exception type?" Commented Feb 3, 2015 at 16:09
  • 1
    This is an opinion, but... IMO it's python, everything is dynamic, it's like cloud of electrons, there no absolutely wrong or right, there are better and worse approaches, which when you apply them will turn out right or wrong, good or bad. I don't understand why would you not throw Arithmetic exceptions if you were implementing e.g. vector class. The latter part of the quote says "[...] but beware that there is nothing to prevent user code from raising an inappropriate error." The documentation explicitly says, user code might use them exceptions, and even might abuse them. Commented Feb 3, 2015 at 16:17

1 Answer 1

1

The Python programmer is given a lot of flexibility with respect to exceptions that can be raised from user code. However, that flexibility doesn't mean that "anything goes." From the version 3 documentation for the Python standard library, the article 5. Built-in Exceptions offers this general guidance.

On what exceptions a programmer can raise:

User code can raise built-in exceptions. This can be used to test an exception handler or to report an error condition “just like” the situation in which the interpreter raises the same exception; but beware that there is nothing to prevent user code from raising an inappropriate error. (emphasis mine)

On programmer-defined exceptions:

The built-in exception classes can be subclassed to define new exceptions; programmers are encouraged to derive new exceptions from the Exception class or one of its subclasses, and not from BaseException. More information on defining exceptions is available in the Python Tutorial under User-defined Exceptions.

Clause 5.1. Base classes suggests that base class exceptions should not typically be raised:

The following exceptions are used mostly as base classes for other exceptions.

BaseException, Exception, ArithmeticError, BufferError, LookupError

Instead, per the guidance in Clause 5.2. Concrete exceptions, it is concrete exceptions that should typically be raised:

The following exceptions are the exceptions that are usually raised.

AssertionError, AttributeError, EOFError, ... OSError, ..., ZeroDivisionError

So, for instance, instead of raising ArithmeticError, consider raising one of its derived classes: FloatingPointError, OverflowError, and ZeroDivisionError. (Or, perhaps a class that you derive from ArithmeticError.)

(And see clause 5.2.1. OS exceptions for more on OSError.)

And finally, on warning messages from the article 29.5. warnings — Warning control:

Warning messages are typically issued in situations where it is useful to alert the user of some condition in a program, where that condition (normally) doesn’t warrant raising an exception and terminating the program. For example, one might want to issue a warning when a program uses an obsolete module.

...

User code can define additional warning categories by subclassing one of the standard warning categories. A warning category must always be a subclass of the Warning class.

Sign up to request clarification or add additional context in comments.

3 Comments

The guidance is quite hard to follow, but the answer is obviously more correct than mine was.
@FilipHaglund By "hard to follow," I'm not sure if you are referring to the Python documentation itself, or my attempt to summarize it. That said, the guidance given in the Python docs appears to me to be looser and less precise than that given by Microsoft for .NET programmers. (For the latter, see the linked article in my question.)
The Python documentation itself. That rule is complicated enough that I'm going to have trouble remembering it for future code reviews.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.