The essentials

Quick reference

One focused task per row. Jump to the related section for complete, working examples.

UseSyntaxExamples
Catch one exceptionexcept ValueError: number = 0View examples
Inspect an exceptionexcept ValueError as error: print(error)View examples
Catch related failuresexcept (TypeError, ValueError) as error: print(error)View examples
Use ordered handlersexcept FileNotFoundError: use_default()View examples
Run after successelse: print(value)View examples
Always clean upfinally: resource.close()View examples
Raise an exceptionraise ValueError("quantity must be positive")View examples
Re-raise the current errorexcept OSError: log_failure(); raiseView examples
Chain a domain errorraise ConfigError("invalid port") from errorView examples
Hide incidental contextraise ValueError("unknown user") from NoneView examples
Define a custom exceptionclass ConfigError(Exception): passView examples
Store error contexterror = ValidationError(field="email", message="invalid address")View examples
Convert at a boundaryvalue = int(text)View examples
Use managed cleanupwith open("settings.txt", encoding="utf-8") as file: data = file.read()View examples
Assert an invariantassert total >= 0, "total cannot be negative"View examples

Catch exceptions only where the program can add context, recover, or translate them into a clearer domain error. Keep try blocks narrow, handle specific exception classes, let unexpected failures propagate, and use context managers for resources that need reliable cleanup.

Step by step

Detailed examples

01

Catch only expected exception types

An except clause also matches subclasses, so order specific handlers before broad base classes. Keep the try suite limited to operations expected to raise those errors; a broad try can accidentally convert an unrelated programming defect into a misleading fallback.

Parse text with specific handlers
def parse_number(text):
    try:
        return int(text)
    except (TypeError, ValueError) as error:
        print(f"invalid number: {error}")
        return 0

print(parse_number("12"))
print(parse_number("twelve"))
Output
12
invalid number: invalid literal for int() with base 10: 'twelve'
0
Order file handlers by specificity
def use_default():
    print("using defaults")

try:
    open("missing-settings.txt", encoding="utf-8")
except FileNotFoundError:
    use_default()
except OSError as error:
    print(f"other file error: {error}")
Output
using defaults
Back to quick reference ↑
02

Separate success work from unconditional cleanup

else runs only when try succeeds and keeps later operations from being caught accidentally. finally runs on every exit path and is appropriate for cleanup, but a with statement is usually clearer for resources implementing the context-manager protocol. Avoid return in finally because it can suppress exceptions and earlier return values.

Success, fallback, and cleanup
def parse(text):
    try:
        value = int(text)
    except ValueError:
        value = 0
    else:
        print(f"parsed {value}")
    finally:
        print("finished")
    return value

print(parse("8"))
print(parse("bad"))
Output
parsed 8
finished
8
finished
0
Back to quick reference ↑
03

Raise, re-raise, and chain errors intentionally

Raise an exception when the current operation cannot satisfy its contract. A bare raise inside a handler preserves the current traceback. Raise from another exception when translating implementation details into a domain error; use from None only when the original context would confuse rather than help diagnosis.

Validate and raise
def require_positive(quantity):
    if quantity <= 0:
        raise ValueError("quantity must be positive")
    return quantity

try:
    require_positive(0)
except ValueError as error:
    print(error)
Output
quantity must be positive
Translate with an explicit cause
class ConfigError(Exception):
    pass

def parse_port(text):
    try:
        return int(text)
    except ValueError as error:
        raise ConfigError("invalid port") from error

try:
    parse_port("http")
except ConfigError as error:
    print(error)
    print(type(error.__cause__).__name__)
Output
invalid port
ValueError
Log and re-raise
try:
    raise OSError("disk unavailable")
except OSError as error:
    print(f"logged: {error}")
    try:
        raise
    except OSError:
        print("propagated")
Output
logged: disk unavailable
propagated
Back to quick reference ↑
04

Model domain failures with custom exceptions

Custom exception types let callers distinguish application failures without parsing message text. Derive normal recoverable errors from Exception, use names ending in Error, and keep structured attributes small and meaningful.

Validation error with attributes
class ValidationError(Exception):
    def __init__(self, field, message):
        self.field = field
        self.message = message
        super().__init__(f"{field}: {message}")

error = ValidationError(field="email", message="invalid address")
print(error)
print(error.field)
Output
email: invalid address
email
Back to quick reference ↑
05

Handle failures at useful boundaries

Low-level helpers should often allow built-in exceptions to propagate so a command, request handler, or job boundary can decide whether to retry, report, or abort. Context managers express cleanup without a wide catch and preserve the original exception if reading fails.

Parse in a helper and handle at the caller
def parse_count(text):
    return int(text)

try:
    value = parse_count("many")
except ValueError:
    value = 0
print(value)
Output
0
Read with managed cleanup
from pathlib import Path
Path("settings.txt").write_text("theme=dark", encoding="utf-8")
with open("settings.txt", encoding="utf-8") as file:
    data = file.read()
print(data)
Output
theme=dark
Back to quick reference ↑
06

Reserve assertions for internal invariants

assert documents a condition that should be impossible to violate when the program is correct. Python can remove assertions when optimization is enabled, so never use them for user input validation, permissions, or other required runtime checks.

Check a calculated invariant
subtotal = 12
discount = 2
total = subtotal - discount
assert total >= 0, "total cannot be negative"
print(total)
Output
10
Back to quick reference ↑

Local code tester

Try Python exception handling

Edit and run the parser locally to practice specific handlers, custom errors, chaining, and cleanup.

Runs in your browser
Output
Press Run to load Python locally.

Sources and further reading

References

Authoritative documentation used to verify and expand this cheat sheet.

  1. Python Software FoundationErrors and Exceptionsdocs.python.org
  2. Python Software FoundationBuilt-in Exceptionsdocs.python.org
  3. Python Software FoundationThe try statementdocs.python.org
  4. Python Software FoundationThe with statementdocs.python.org

Help us improve

Found a typo or missing example?

Tell us what would make this cheat sheet clearer, more complete, or more useful.

Share feedback