Learn the concept
A context manager defines setup and cleanup around a block. The with statement makes ownership of a resource visible and ensures its exit behavior runs when the block ends, including when an exception occurs.
Files and many database connections offer context-manager behavior, but the exact contract varies. A database transaction context may commit or roll back without closing the connection. Read the resource’s contract rather than assuming every with statement closes everything.
For your own manager, use contextlib.contextmanager when a simple generator-based implementation is sufficient. Put cleanup in finally so it runs when the body raises. Do not suppress exceptions unless that is the deliberate documented behavior.
Run and inspect
from contextlib import contextmanager
events = []
@contextmanager
def session():
events.append("open")
try:
yield "resource"
finally:
events.append("close")
with session() as resource:
assert resource == "resource"
assert events == ["open", "close"]
Your exercise
Raise an exception inside the managed block and verify cleanup still happens. Compare the behavior with manual setup that has no finally block.
Check your understanding
Cleanup runs once and the original exception is not silently converted into a successful result.