Overview

14 Exceptions

Exceptions provide a structured, readable way to deal with unusual situations at runtime, replacing ad hoc checks or error codes that clutter logic and duplicate “plumbing” across many functions. The chapter motivates exceptions with scenarios like saving a document when disk space runs out, contrasting three approaches: ignoring errors, propagating status values, and using exceptions to raise an error once and handle it in one well-chosen place. It also frames Python’s philosophy as “easier to ask forgiveness than permission” (EAFP), encouraging straightforward code that tries an operation and handles problems only if they occur, rather than exhaustively pre-checking conditions (LBYL).

Python implements exceptions as classes in a hierarchy, making it possible to catch broad or specific problems and to define custom exceptions (recommended to subclass Exception, not BaseException). Exceptions can be raised by built-ins or explicitly with raise, then matched by type in try/except blocks, with optional else (runs on success) and finally (runs regardless) clauses; ordering of handlers matters because of inheritance. The chapter surveys common built-ins, best practices (avoid bare except, catch only what you intend), debugging with assert (a specialized raise that’s disabled under optimization), and newer capabilities like ExceptionGroup and except* (Python 3.11+) for handling multiple concurrent errors.

Beyond error recovery, exceptions can simplify normal control flow, as shown by examples that centralize I/O failure handling or treat invalid spreadsheet cells uniformly. The chapter also highlights context managers via the with keyword, which guarantee setup/cleanup (for files, locks, transactions, etc.), allow multiple managers, and support multi-line formatting for readability, making resource handling safer and clearer than manual try/finally. A concluding lab refactors a word-frequency module to add targeted exception handling, and the discussion cautions against overusing broad try/except or masking useful tracebacks—reinforcing the theme of precise, minimal, and purposeful exception design.

Summary

  • Python’s philosophy is that errors shouldn’t pass silently unless they’re explicitly silenced.
  • Python’s exception-handling mechanism and exception classes provide a rich system to handle runtime errors in your code.
  • Python exception types are organized in a hierarchy because exceptions, like all objects in Python, are based on classes.
  • By using try, except, else, and finally blocks, and by selecting and even creating the types of exceptions caught, you can have very fine-grained control over how exceptions are handled and ignored.
  • You can define a new exception by inheriting (preferably) from Exception.
  • Exceptions can be conditionally raised but using an assert statement.
  • Invoking a context manager by using the with keyword can ensure actions even if an exception occurs, as in reading or writing a file.

FAQ

What is an exception in Python and what happens when one is raised?An exception is an object that represents an unusual condition during execution. It’s created and raised with the raise statement. When raised, Python stops normal flow and searches up the call stack for the nearest matching try/except handler. If found, the handler runs (and can inspect the exception object). If none is found, the program terminates with a traceback.
Why use exceptions instead of returning error codes?Returning status codes forces every function to check and relay errors, creating repetitive “plumbing” code and scattering handling logic across the call chain. Exceptions let you write the normal path once and centralize handling where it belongs (for example, a top-level save routine), producing clearer, less error-prone code.
How do I raise an exception, and what should I pass to it?Use raise ExceptionType(arguments), for example raise ValueError("Invalid input"). Arguments typically include helpful context (messages or data). They’re stored on the exception (commonly accessible via e.args) and appear in the traceback if unhandled.
How do I catch exceptions, and what do else and finally do?Wrap code in try and handle specific errors with one or more except clauses, optionally binding the exception to a variable: except ValueError as e:. You can catch multiple types with a tuple: except (TypeError, ValueError) as e:. else runs only if no exception occurred. finally always runs (success or failure) and is ideal for cleanup like closing files. Avoid a bare except: in production because it hides all errors.
How does the exception hierarchy affect which handler runs?Exceptions are classes in a hierarchy. A more general handler (for a base class) will also catch its subclasses. Therefore, order specific handlers before general ones. For example, handle IndexError before LookupError; otherwise the broader LookupError handler will preempt the specific one.
What’s the difference between Exception and BaseException, and how should I subclass?Most exceptions inherit from Exception. A few critical ones (like KeyboardInterrupt, SystemExit) inherit from BaseException. Catching Exception won’t intercept KeyboardInterrupt (so Ctrl-C still works). Define your custom exceptions as subclasses of Exception, not BaseException.
What is Python’s EAFP approach compared to LBYL?LBYL (“look before you leap”) checks for problems in advance; EAFP (“easier to ask forgiveness than permission”) just tries the operation and handles exceptions if they occur. Python favors EAFP: it keeps code concise and focuses error handling where it’s needed rather than spreading prechecks everywhere.
What are ExceptionGroup and except* used for?ExceptionGroup (Python 3.11+) bundles multiple exceptions (useful in concurrent code). Use except* to handle matching exceptions within the group; each except* clause processes only the exceptions of its specified type. This lets you handle several failure types from one operation in a single structured block.
How does the assert statement work, and when is it disabled?assert expression, message raises AssertionError (with the optional message) if the expression is False and __debug__ is True. Assertions are removed when optimization is enabled (run Python with -O or -OO, or set PYTHONOPTIMIZE), making them great for development-time checks with no runtime cost in optimized runs.
What are context managers and how does with help with cleanup?Context managers manage setup/teardown around a block. Using with guarantees cleanup even if an exception occurs, e.g., with open(fname) as f: ensures the file closes. You can manage multiple contexts and, since Python 3.10, split long with statements across lines with parentheses. They’re ideal for files, locks, and transactions; you can build your own (see contextlib).

pro $24.99 per month

  • access to all Manning books, MEAPs, liveVideos, liveProjects, and audiobooks!
  • choose one free eBook per month to keep
  • exclusive 50% discount on all purchases
  • renews monthly, pause or cancel renewal anytime

lite $19.99 per month

  • access to all Manning books, including MEAPs!

team

5, 10 or 20 seats+ for your team - learn more


choose your plan

team

monthly
annual
$49.99
$499.99
only $41.67 per month
  • five seats for your team
  • access to all Manning books, MEAPs, liveVideos, liveProjects, and audiobooks!
  • choose another free product every time you renew
  • choose twelve free products per year
  • exclusive 50% discount on all purchases
  • renews monthly, pause or cancel renewal anytime
  • renews annually, pause or cancel renewal anytime
  • The Quick Python Book, Fourth Edition ebook for free
choose your plan

team

monthly
annual
$49.99
$499.99
only $41.67 per month
  • five seats for your team
  • access to all Manning books, MEAPs, liveVideos, liveProjects, and audiobooks!
  • choose another free product every time you renew
  • choose twelve free products per year
  • exclusive 50% discount on all purchases
  • renews monthly, pause or cancel renewal anytime
  • renews annually, pause or cancel renewal anytime
  • The Quick Python Book, Fourth Edition ebook for free
choose your plan

team

monthly
annual
$49.99
$499.99
only $41.67 per month
  • five seats for your team
  • access to all Manning books, MEAPs, liveVideos, liveProjects, and audiobooks!
  • choose another free product every time you renew
  • choose twelve free products per year
  • exclusive 50% discount on all purchases
  • renews monthly, pause or cancel renewal anytime
  • renews annually, pause or cancel renewal anytime
  • The Quick Python Book, Fourth Edition ebook for free