Syntax Cache
BlogMethodFeaturesHow It WorksBuild a Game
  1. Home
  2. Cheat Sheets
  3. Python
  4. Python Error Handling Cheat Sheet
PythonCheat Sheet

Python Error Handling Cheat Sheet

Quick-reference for exception handling patterns. Each section includes copy-ready snippets with inline output comments.

On this page
  1. 1try / except / else / finally
  2. 2Catching Specific Exceptions
  3. 3raise and re-raise
  4. 4Custom Exception Classes
  5. 5Exception Chaining (raise ... from ...)
  6. 6Context Managers (__enter__ / __exit__)
  7. 7assert Statements
  8. 8Common Built-in Exceptions
try / except / else / finallyCatching Specific Exceptionsraise and re-raiseCustom Exception ClassesException Chaining (raise ... from ...)Context Managers (__enter__ / __exit__)assert StatementsCommon Built-in Exceptions

try / except / else / finally

The full four-part structure: try (risky code), except (error recovery), else (success-only), finally (always runs).

Complete structure
try:
    result = int(user_input)         # risky code
except ValueError as e:
    print(f'Invalid: {e}')           # recovery
    result = 0
else:
    print(f'Parsed: {result}')       # only if no exception
finally:
    print('Done')                    # always runs
Minimal try/except
try:
    value = int('abc')
except ValueError:
    value = 0
value   # => 0
Why use else?
# else keeps the try block minimal.
# Exceptions in else are NOT caught by the preceding except.
try:
    data = json.load(f)
except json.JSONDecodeError:
    data = {}
else:
    process(data)   # error here propagates normally

Catching Specific Exceptions

Always catch the most specific exception possible. Bare except: and except Exception are usually too broad.

Catch multiple types
try:
    result = operation()
except (ValueError, TypeError) as e:
    print(f'Error: {e}')
Separate handlers
try:
    with open('config.json') as f:
        config = json.load(f)
except FileNotFoundError:
    config = {}                      # missing file is OK
except json.JSONDecodeError as e:
    print(f'Malformed JSON: {e}')
    config = {}
Common built-in exceptions
# ValueError    — wrong value ('abc' to int)
# TypeError     — wrong type (1 + 'a')
# KeyError      — missing dict key
# IndexError    — list index out of range
# FileNotFoundError — file does not exist
# AttributeError   — missing attribute
# ZeroDivisionError — division by zero
Exception vs BaseException
# except Exception:      catches normal errors (recommended)
# except BaseException:   also catches KeyboardInterrupt, SystemExit
# except:                 same as BaseException (avoid!)

Never use bare except: — it catches Ctrl+C and prevents clean shutdown.

raise and re-raise

Raise an exception
def validate_age(age):
    if age < 0:
        raise ValueError(f'Age cannot be negative: {age}')
    return age
Re-raise the current exception
try:
    process(data)
except Exception:
    logging.exception('Processing failed')
    raise   # re-raise the same exception

Use bare raise (no argument) to preserve the original traceback.

Raise from (exception chaining)
try:
    data = json.loads(raw)
except json.JSONDecodeError as e:
    raise ConfigError('Invalid config') from e
# Traceback shows: "The above exception was the direct cause..."
Suppress chaining
raise AppError('...') from None
# Hides the original exception (use sparingly)

Custom Exception Classes

Create domain-specific exceptions by inheriting from Exception. Use a base class for your app.

Simple custom exception
class ConfigError(Exception):
    """Raised when configuration is invalid."""
    pass

raise ConfigError('Missing required field: name')
Exception hierarchy
class AppError(Exception):
    """Base for all app errors."""
    pass

class NotFoundError(AppError):
    pass

class ValidationError(AppError):
    def __init__(self, field, message):
        self.field = field
        super().__init__(f'{field}: {message}')
Catch by base class
try:
    load_config()
except AppError as e:
    # Catches NotFoundError, ValidationError, etc.
    print(f'App error: {e}')

Exception Chaining (raise ... from ...)

Preserve the original exception context when translating errors between layers.

Explicit chaining
try:
    user = db.get_user(user_id)
except DatabaseError as e:
    raise UserNotFoundError(f'User {user_id}') from e
# Traceback shows both exceptions with clear causal link
Implicit chaining (without from)
try:
    user = db.get_user(user_id)
except DatabaseError:
    raise UserNotFoundError(f'User {user_id}')
# Still chains via __context__, but message says:
# "During handling of the above exception, another exception occurred"

Use from for deliberate translation. Without from, Python chains implicitly but the intent is unclear.

Access chained exceptions
try:
    load_config()
except ConfigError as e:
    print(e.__cause__)     # explicit chain (from)
    print(e.__context__)   # implicit chain

Context Managers (__enter__ / __exit__)

The with statement ensures cleanup runs even on exceptions. Prefer it over try/finally.

Built-in context managers
with open('data.txt') as f:
    data = f.read()
# f.close() called automatically

import threading
lock = threading.Lock()
with lock:
    # critical section
    pass
Custom context manager (class)
class Timer:
    def __enter__(self):
        self.start = time.perf_counter()
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.elapsed = time.perf_counter() - self.start
        print(f'Elapsed: {self.elapsed:.4f}s')
        return False   # don't suppress exceptions

with Timer() as t:
    do_work()
@contextmanager (decorator shortcut)
from contextlib import contextmanager

@contextmanager
def timer():
    start = time.perf_counter()
    yield
    print(f'Elapsed: {time.perf_counter() - start:.4f}s')

with timer():
    do_work()

assert Statements

assert is for debugging invariants, not for input validation. Assertions are stripped when running with python -O.

Basic assert
def process(items):
    assert len(items) > 0, 'items must not be empty'
    # ...
When to use assert
# Good: internal invariants / developer mistakes
assert isinstance(result, dict), f'Expected dict, got {type(result)}'

# Bad: user input validation (stripped with -O!)
# assert user_age > 0   # Don't do this!
if user_age <= 0:
    raise ValueError('Age must be positive')
Assert with expression
# assert condition, "message"
# Raises AssertionError if condition is False
assert 0 < x < 100, f'x out of range: {x}'

Never use assert for security or input validation. Use raise ValueError instead.

Common Built-in Exceptions

Type and value errors
int('abc')          # ValueError
1 + 'a'             # TypeError
len(42)             # TypeError
Lookup errors
d = {'a': 1}
d['z']              # KeyError: 'z'
items = [1, 2]
items[5]            # IndexError: list index out of range
Attribute and name errors
'hello'.foo         # AttributeError
print(undefined)    # NameError
I/O and OS errors
open('missing.txt')       # FileNotFoundError
open('/etc/shadow')       # PermissionError
1 / 0                     # ZeroDivisionError
Exception hierarchy (partial)
# BaseException
#   +-- SystemExit
#   +-- KeyboardInterrupt
#   +-- Exception
#       +-- ValueError
#       +-- TypeError
#       +-- LookupError
#       |   +-- KeyError
#       |   +-- IndexError
#       +-- OSError
#       |   +-- FileNotFoundError
#       |   +-- PermissionError
#       +-- RuntimeError
#       +-- StopIteration
Learn Python in Depth
Python Decorators Practice →Python OOP Practice →Python Loops Practice →
Warm-up1 / 2

Can you write this from memory?

Write a try/except skeleton that catches Exception. Use pass in both blocks.

See Also
File I/O →Decorators →f-strings →OOP →

Start Practicing Python

Free daily exercises with spaced repetition. No credit card required.

← Back to Python Syntax Practice
Syntax Cache

Build syntax muscle memory with spaced repetition.

Product

  • Pricing
  • Our Method
  • Daily Practice
  • Design Patterns
  • Interview Prep

Resources

  • Blog
  • Compare
  • Cheat Sheets
  • Vibe Coding
  • Muscle Memory

Languages

  • Python
  • JavaScript
  • TypeScript
  • Rust
  • SQL
  • GDScript

Legal

  • Terms
  • Privacy
  • Contact

© 2026 Syntax Cache

Cancel anytime in 2 clicks. Keep access until the end of your billing period.

No refunds for partial billing periods.