Definition
A context manager sets something up and guarantees it's cleaned up afterwards, even if an error occurs. It's used with the with statement, and a class can provide one by defining __enter__ and __exit__. The contextlib module makes writing one easier.
In simple words
It's a library book rule: borrow on entry, and return on exit, no matter what happened while you were reading. with open(...) closes the file for you, even if your code crashes.
Why it matters
Files, database connections, locks and GPU memory all need reliable cleanup. Forgetting to clean up leads to leaks that appear only after hours of running.
How it works
| You've seen it as | Cleans up |
|---|---|
| with open(path) as f | Closes the file |
| with lock: | Releases the lock |
| with torch.no_grad(): | Turns gradients back on |
| with tempfile.TemporaryDirectory() | Deletes the folder |
In code
from contextlib import contextmanager
import time
class Timer:
def __enter__(self):
self.start = time.perf_counter()
return self
def __exit__(self, kind, value, traceback):
print("Finished, error was:", kind.__name__ if kind else None)
return False # False: don't hide the error
with Timer():
sum(range(1000))
@contextmanager
def tag(name):
print(f"<{name}>")
try:
yield
finally:
print(f"</{name}>")
try:
with tag("b"):
raise ValueError("oops")
except ValueError:
print("The closing tag still printed")Output
Finished, error was: None <b> </b> The closing tag still printed
Common mistakes
- Opening files without with, and forgetting to close them.
- Returning True from __exit__ without meaning to, which silently swallows errors.
Check yourself
Summary
- Context managers guarantee cleanup.
- Use with for files and anything else that needs closing.
Finished reading?
Sources: Python docs: contextlib