python-context-managers
Table of Contents
Python context managers
Python context managers are objects that define __enter__ and __exit__ to manage setup and teardown around a with block. They guarantee cleanup runs even if an exception occurs, making them ideal for resource management (files, locks, database connections).
Context managers eliminate try/finally boilerplate and make resource handling declarative and clear.
Example
This example implements a context manager for database connections and timing.
# run: python3 context_managers.py # description: custom context manager for resource management import time class DatabaseConnection: def __init__(self, name): self.name = name self.connected = False def __enter__(self): print(f"Connecting to {self.name}...") time.sleep(0.1) # simulate connection time self.connected = True return self def __exit__(self, exc_type, exc_val, exc_tb): print(f"Disconnecting from {self.name}...") self.connected = False if exc_type is not None: print(f"Exception occurred: {exc_type.__name__}: {exc_val}") return False # don't suppress exception def query(self, sql): if not self.connected: raise RuntimeError("Not connected") return f"Result of: {sql}" # Use context manager with DatabaseConnection("MyDB") as db: print(db.query("SELECT * FROM users")) print("Connection closed after with block\n") # Exception handling try: with DatabaseConnection("MyDB") as db: print(db.query("SELECT * FROM users")) raise ValueError("Bad query") except ValueError: print("Caught exception (cleanup still ran)")
Common patterns
Decorator approach (simpler for simple cases):
@contextlib.contextmanagerdecorator on generator function- Yield the resource; code after yield runs on exit
- Cleaner than writing a class with
__enter__and__exit__
Return value from __enter__:
- Often
return selfto access the resource - Can return a different object
- Assigned to the variable after
asinwithstatement
__exit__ parameters:
exc_type: exception class (None if no exception)exc_val: exception instanceexc_tb: exception traceback- Return
Trueto suppress the exception;Falseto re-raise
Generator version:
from contextlib import contextmanager @contextmanager def database(name): print(f"Connecting to {name}...") try: yield None # resource goes here finally: print(f"Disconnecting from {name}...")
Nested contexts:
- Multiple
withstatements can nest:with A() as a, B() as b: - Or traditional nesting:
with A() as a: with B() as b: - Resources acquired in order; cleaned up in reverse
Common uses:
- File handling (
with open(...)) - Locks and mutexes (
with lock:) - Database transactions (
with db.transaction():) - Temporary directory changes (
with chdir(...)) - Timing/profiling (
with timer():) - Mocking and patching (
with patch(...):)
python-context-managers.md · Last modified: by 127.0.0.1
