Exception Hierarchy Python (58/100 Days of Python)

Martin Mirakyan
4 min readFeb 28, 2023

--

Day 58 of the “100 Days of Python” blog post series covering exceptions hierarchy

In Python, exceptions are a way to handle errors and other exceptional events that may occur during program execution. Python’s exception hierarchy provides a well-organized way to categorize and handle different types of exceptions. The defined exception structure also provides a deterministic way of handling different types of exceptions with except blocks.

The Exception Hierarchy

In Python, all exceptions are derived from the BaseException class. This means that every exception in Python is an instance of BaseException or one of its subclasses.

The BaseException class is the top-level class in the exception hierarchy. It provides some common methods that all exceptions can use, such as __str__ and __repr__. However, you should not use BaseException directly in your code as it is too broad and can catch any type of exception.

Instead, you should use more specific exception classes that are subclasses of BaseException. Python provides a number of built-in exception classes that you can use, and you can also create your own custom exception classes.

The following diagram shows the hierarchy of built-in exception classes in Python (taken from the official Python documentation):

BaseException
├── BaseExceptionGroup
├── GeneratorExit
├── KeyboardInterrupt
├── SystemExit
└── Exception
├── ArithmeticError
│ ├── FloatingPointError
│ ├── OverflowError
│ └── ZeroDivisionError
├── AssertionError
├── AttributeError
├── BufferError
├── EOFError
├── ExceptionGroup [BaseExceptionGroup]
├── ImportError
│ └── ModuleNotFoundError
├── LookupError
│ ├── IndexError
│ └── KeyError
├── MemoryError
├── NameError
│ └── UnboundLocalError
├── OSError
│ ├── BlockingIOError
│ ├── ChildProcessError
│ ├── ConnectionError
│ │ ├── BrokenPipeError
│ │ ├── ConnectionAbortedError
│ │ ├── ConnectionRefusedError
│ │ └── ConnectionResetError
│ ├── FileExistsError
│ ├── FileNotFoundError
│ ├── InterruptedError
│ ├── IsADirectoryError
│ ├── NotADirectoryError
│ ├── PermissionError
│ ├── ProcessLookupError
│ └── TimeoutError
├── ReferenceError
├── RuntimeError
│ ├── NotImplementedError
│ └── RecursionError
├── StopAsyncIteration
├── StopIteration
├── SyntaxError
│ └── IndentationError
│ └── TabError
├── SystemError
├── TypeError
├── ValueError
│ └── UnicodeError
│ ├── UnicodeDecodeError
│ ├── UnicodeEncodeError
│ └── UnicodeTranslateError
└── Warning
├── BytesWarning
├── DeprecationWarning
├── EncodingWarning
├── FutureWarning
├── ImportWarning
├── PendingDeprecationWarning
├── ResourceWarning
├── RuntimeWarning
├── SyntaxWarning
├── UnicodeWarning
└── UserWarning

This means that the FileNotFoundError is a subclass of an OSError, which is a subclass of the Exception class, which itself inherits from the BaseException.

Handling multiple exceptions with a single except statement

To handle multiple exceptions with a single except statement, you can specify a tuple of exception types to catch, like this:

try:
# some code that may raise an exception
except (ExceptionType1, ExceptionType2):
# handle the exception

In this example, both ExceptionType1 and ExceptionType2 are exceptions that you want to catch. If the code in the try block raises an instance of either of these exceptions, the code in the except block will execute.

Here’s an example with specific exception types:

try:
# some code that may raise an exception
except (TypeError, ValueError):
# handle the exception

In this example, if the code in the try block raises either a TypeError or a ValueError, the code in the except block will execute.

Handling multiple exceptions with multiple except statements

Alternatively, you can handle multiple exceptions with multiple except statements. In this case, each except statement handles a different exception type:

try:
# some code that may raise an exception
except TypeError:
# handle the TypeError
except ValueError:
# handle the ValueError

In this example, if the code in the try block raises a TypeError, the code in the first except block will execute. If the code raises a ValueError, the code in the second except block will execute.

Respecting the exception hierarchy

When using multiple except statements, it's important to respect the exception hierarchy in Python. This means that if you catch a base exception class, such as Exception, you should catch more specific exceptions before it. If you write an except statement of a more specific class after the base class, the block won’t be executed:

try:
# some code that may raise an exception
except ValueError:
# handle the ValueError
except Exception:
# handle any other exception

In this example, the ValueError exception is caught first. If the code raises any other exception that is derived from Exception, the code in the second except block will execute.

However, it is not recommended to catch Exception directly, as it is too broad and can catch any type of exception. It's better to catch more specific exceptions whenever possible:

try:
# some code that may raise an exception
except TypeError:
# handle the TypeError
except ValueError:
# handle the ValueError
except Exception:
# handle any other exception

In this example, if the code in the try block raises a TypeError or a ValueError, the corresponding except block will execute. If the code raises any other exception that is derived from Exception, the code in the third except block will execute.

If we place the base exception as the first except block, it will prevent the rest from being ever executed:

try:
# some code that may raise an exception
except Exception as e:
print(f'An error occurred: {e}') # This will catch all the errors
except ValueError:
print('A ValueError occurred') # This will never be executed
except TypeError:
print('A TypeError occurred') # This will never be executed

In this example, the try block may raise any type of exception. However, the first except statement catches the base Exception class, so it will catch any exception that is raised. The error message will be printed and the rest of the except statements will not be executed.

What’s next?

--

--