`contextlib` — Context Manager Utilities
Python · Standard Library · Run with python3
Explanation
`contextlib` provides utilities for creating and composing context managers. `@contextmanager` turns a generator function into a context manager. `suppress(*exceptions)` silences specific exceptions. `ExitStack` dynamically composes a variable number of context managers. `nullcontext` is a no-op context manager useful as a conditional placeholder. `closing` wraps objects with a `close()` method.
Real-World Scenario
An integration test needs to open a variable number of temporary files (count known only at runtime). `ExitStack` opens each file and registers it — all are guaranteed closed when the `with` block exits, even if some openings fail mid-loop. ```python import contextlib import tempfile from pathlib import Path # suppress — clean alternative to try/except/pass with contextlib.suppress(FileNotFoundError): Path("nonexistent_file.txt").unlink() print("File removed or didn't exist") # ExitStack — dynamic set of context managers with contextlib.ExitStack() as stack: temps = [ stack.enter_context(tempfile.NamedTemporaryFile(suffix=".txt")) for _ in range(3) ] for i, f in enumerate(temps): f.write(f"File {i}".encode()) f.flush() print(f"Created {len(temps)} temp files") # All closed automatically here # Reusable context manager factory @contextlib.contextmanager def temp_directory(): import tempfile, shutil d = tempfile.mkdtemp() try: yield Path(d) finally: shutil.rmtree(d) ```
Quick Snippet
import contextlib
import tempfile
from pathlib import Path
# suppress — clean alternative to try/except/pass
with contextlib.suppress(FileNotFoundError):
Path("nonexistent_file.txt").unlink()
print("File removed or didn't exist")
# ExitStack — dynamic set of context managers
with contextlib.ExitStack() as stack:
temps = [
stack.enter_context(tempfile.NamedTemporaryFile(suffix=".txt"))
for _ in range(3)
]
for i, f in enumerate(temps):
f.write(f"File {i}".encode())
f.flush()
print(f"Created {len(temps)} temp files")
# All closed automatically here
# Reusable context manager factory
@contextlib.contextmanager
def temp_directory():
import tempfile, shutil
d = tempfile.mkdtemp()
try:
yield Path(d)
finally:
shutil.rmtree(d)Full Example
# Compile: python3 contextlib_basics.py
# Output:
# File removed or didn't exist
# Created 3 temp files
import contextlib
import tempfile
from pathlib import Path
with contextlib.suppress(FileNotFoundError):
Path("nonexistent_file.txt").unlink()
print("File removed or didn't exist")
with contextlib.ExitStack() as stack:
temps = [
stack.enter_context(tempfile.NamedTemporaryFile(suffix=".txt"))
for _ in range(3)
]
for i, f in enumerate(temps):
f.write(f"File {i}".encode())
f.flush()
print(f"Created {len(temps)} temp files")
@contextlib.contextmanager
def temp_directory():
import shutil
d = tempfile.mkdtemp()
try:
yield Path(d)
finally:
shutil.rmtree(d)
with temp_directory() as td:
(td / "test.txt").write_text("hello")
files = list(td.glob("*"))
print(f"Files in temp dir: {[f.name for f in files]}")
print("Temp dir cleaned up")
python3 contextlib_basics.py