Skip to Content

Why reach for context managers over try/finally?

Category: Python Fundamentals

Answer

with syntax guarantees __exit__ runs even on exceptions, and the read intent stays obvious. try/finally works but adds bracket noise. Custom context managers turn resource pairs into ONE line of intent: locks, DB sessions, temporary files, telemetry spans.

Concrete examples from the fca project context

Example 1

with lock: critical_section() - exit() always releases even on exception.

Example 2

with open(path) as f: read() - file closes even on partial reads.

Example 3

with transaction(): write() - rollback on exception, commit on success.

Example 4

@contextmanager wraps a generator into a with-statement.

Data flow / flow chart

with cm:
  protected block
  __exit__ runs ALWAYS
  (try/finally: same guarantee, more noise)

Takeaway

Use with for every resource pair. __enter__/__exit__ is the cleanest abstraction.