This is a searchable reference for Python’s built-in exception hierarchy — the class tree that every error in the standard library belongs to. For each exception it shows the direct parent class, the attributes it carries, and a plain-English description of what typically triggers it, so you can decide exactly what to catch and how to handle it.
The hierarchy at a glance
BaseException
├── SystemExit
├── KeyboardInterrupt
├── GeneratorExit
└── Exception
├── ArithmeticError
│ ├── ZeroDivisionError
│ ├── OverflowError
│ └── FloatingPointError
├── LookupError
│ ├── KeyError
│ └── IndexError
├── OSError (aliases: IOError, EnvironmentError)
│ ├── FileNotFoundError (errno ENOENT)
│ ├── PermissionError (errno EACCES)
│ ├── FileExistsError (errno EEXIST)
│ ├── IsADirectoryError (errno EISDIR)
│ └── TimeoutError (errno ETIMEDOUT)
├── ValueError
├── TypeError
├── AttributeError
├── NameError
│ └── UnboundLocalError
├── RuntimeError
│ └── RecursionError
└── StopIteration
SystemExit, KeyboardInterrupt, and GeneratorExit derive directly from BaseException, not Exception, so a bare except Exception does not catch them. This is intentional: a Ctrl-C or a sys.exit() call should not be silently absorbed by general error handlers.
Catching exceptions: the specificity rule
Always catch the most specific class you can actually handle. Catching a parent class handles the whole family beneath it:
try:
value = config["timeout"] # may raise KeyError
fh = open(path) # may raise FileNotFoundError
except KeyError:
value = 30 # sensible default
except FileNotFoundError as e:
print(f"missing {e.filename}") # OSError subclass with errno/filename
Because FileNotFoundError is a subclass of OSError, an except OSError would also catch it — useful when you do not care which I/O error occurred, only that one did.
OSError attributes
OSError and all its subclasses expose three key attributes:
errno— the numeric POSIX error code (e.g., 2 for ENOENT)strerror— the human-readable message (e.g., “No such file or directory”)filename— the path involved, if applicable
These let you react differently to different failure modes without matching on string messages.
Defining your own exceptions
Custom exceptions should subclass Exception (or a more specific base like ValueError), not BaseException. A typical pattern:
class AppConfigError(ValueError):
"""Raised when required configuration is missing or invalid."""
pass
Subclassing ValueError lets calling code catch AppConfigError specifically or catch all value-like errors with except ValueError when it needs a broader net.
The exception context: chaining with raise ... from
Python 3 preserves the original exception when a new one is raised inside an except block, making tracebacks more informative:
try:
data = json.loads(raw)
except json.JSONDecodeError as e:
raise ValueError("Invalid config format") from e
The from e syntax explicitly chains the exceptions. The traceback shows both: the JSONDecodeError as the cause, and the ValueError as the raised exception. Without from e, Python still chains them implicitly (as “during handling of the above exception”), but explicit chaining makes the intent clearer. Use raise X from None to suppress the chain when the cause is an internal implementation detail not relevant to the caller.
Everything runs in your browser; nothing is uploaded.