with-blocks acquire and always release a resource—cleanup guaranteed, even on error.
A block that guarantees cleanup. Whatever happens inside — success, exception, early return — the file gets closed and the lock gets released.
It's how you stop leaking connections, file handles and locks, which is the most common source of mysterious production exhaustion.
A context manager pairs setup and teardown around a block via the with statement. __enter__ acquires a resource and returns a handle; __exit__ releases it when the block ends—and runs even if the block raises, so cleanup is guaranteed. contextlib.contextmanager lets you write one as a generator.
A context manager guarantees a resource is cleaned up. with obj calls obj.__enter__ on the way in and obj.__exit__ on the way out—crucially, __exit__ runs even if the block raises, so files close, locks release, and transactions roll back no matter what. It's essentially a foolproof try/finally. The easiest way to write one is the @contextmanager decorator over a generator, where code before yield is setup and code after is teardown.
[Practice Problems] Python Context Managers - Visually Explained — Visually Explained, 7:05