Exceptions & custom exceptions
try/except/else/finally, raising, the exception hierarchy, custom exception classes, chaining and EAFP.
Things go wrong: files go missing, users type letters where numbers belong, networks time out. Python reports problems by raising exceptions. Good programs anticipate the failures they can handle, deal with them gracefully, and let the unexpected ones fail loudly. This lesson covers try/except/else/finally, raising exceptions, the exception hierarchy, and designing your own exception classes.
What an exception looks like#
An unhandled exception stops the program and prints a traceback. Read it bottom-up: the exception type (IndexError), its message, then the chain of calls that led there.
Common built-in exceptions you'll meet constantly:
Catching exceptions with try/except#
Python runs the try block. If a ValueError occurs, it jumps to the matching except block; otherwise the except block is skipped.
Several exception types
You can also group types: except (KeyError, IndexError):.
else and finally#
The full form has four parts:
elsekeeps thetryblock minimal — only the line that might fail goes intry, so you don't accidentally catch errors from other code.finallyis for cleanup that must always happen (closing connections, releasing locks). In practice,withstatements handle most cleanup for you.
Raising exceptions#
Use raise to signal that your function can't do its job:
Raising is better than returning a special value like -1 or None: callers can't accidentally ignore it, and the message explains what happened.
Inside an except block, a bare raise re-raises the current exception — useful when you want to log something but still let the error propagate:
The exception hierarchy#
Exceptions are classes arranged in a hierarchy, and except SomeClass also catches all of its subclasses:
Order your except clauses from most specific to most general, because the first match wins.
Don't swallow everything
This prints nothing and hides a typo. A bare except: is even worse — it also catches KeyboardInterrupt, so Ctrl+C stops working. Catch only what you expect and can handle. The one legitimate place for a broad except Exception is at the very top of a program or request handler, where you log the error (with traceback) before continuing.
Custom exceptions#
For your own applications and libraries, define exception classes that describe your domain's failures. Callers can then catch exactly what they care about:
Best practices:
- Inherit from
Exception(never directly fromBaseException). - Create one base exception per module or package (
BankError) and derive specific ones from it. - Name them with an
Errorsuffix. - Store useful data as attributes, and pass a clear message to
super().__init__.
Exception chaining#
When you catch a low-level error and raise a higher-level one, use raise ... from ... to keep the original cause in the traceback:
Exception groups (Python 3.11+)#
When several operations fail at once — common with concurrent tasks — Python can raise an ExceptionGroup, handled with except*:
You'll see these with asyncio.TaskGroup in the concurrency lesson.
EAFP vs LBYL#
Python culture favours EAFP — "Easier to Ask Forgiveness than Permission": just try the operation and handle the failure, rather than checking everything first (LBYL, "Look Before You Leap").
EAFP avoids race conditions (a file can disappear between checking and opening it) and often reads more directly. For simple dict lookups, config.get("timeout", 30) is shorter still.
Common mistakes#
- Catching too broadly (
except:/except Exception: pass). - Huge
tryblocks — wrap only the line that can fail; useelsefor the rest. - Using exceptions for normal control flow in hot loops when a simple
ifwould do. - Losing the original error — use
raise ... from e. - Raising strings:
raise "error"is aTypeError; raise exception instances.
What's next#
Custom exceptions are classes — which brings us to one of Python's biggest topics: object-oriented programming, starting with classes and objects.
Check your understanding
Quick quiz
1.When does the
elseblock of atrystatement run?2.Why is a bare
except:(orexcept Exception:that does nothing) dangerous?3.How should a custom exception be defined?
Finished reading?
Mark this lesson complete to track your progress.