Python Advanced
Python Context Managers
Context managers let you set up and automatically clean up resources like files or connections using the with statement, so you never forget to close something.
The with Statement
You have likely already used a context manager without naming it: opening a file with the with statement. It guarantees that setup code runs before your block and cleanup code runs after, even if an exception occurs inside the block.
with open("data.txt") as f:
content = f.read()
print(content)
# file is automatically closed here__enter__ and __exit__
A context manager is any object with two special methods: __enter__, which runs at the start of the with block and returns the value used after "as", and __exit__, which runs at the end, even after an exception, and can suppress it.
class Timer:
def __enter__(self):
import time
self.start = time.time()
return self
def __exit__(self, exc_type, exc_value, traceback):
import time
elapsed = time.time() - self.start
print(f"Took {elapsed:.4f} seconds")
with Timer():
total = sum(range(1_000_000))contextlib.contextmanager
Writing a full class just for a context manager can feel heavy. The contextlib module gives you a decorator that turns a simple generator function into a context manager: code before yield is __enter__, code after yield is __exit__.
from contextlib import contextmanager
@contextmanager
def open_section(title):
print(f"--- start {title} ---")
yield
print(f"--- end {title} ---")
with open_section("Report"):
print("writing report contents")Use context managers for anything that needs guaranteed cleanup: files, database connections, locks, and network sockets.
| Approach | Best for |
|---|---|
| Class with __enter__/__exit__ | Reusable, stateful resources |
| @contextmanager generator | Quick, one-off setup/cleanup logic |
If __exit__ returns True, any exception raised inside the with block is silently suppressed — use that carefully.
