Phase 11 of 25 · Topic 11.3

contextlib Module: @contextmanager Generator Helper

1Concept

`contextlib.contextmanager` transforms a generator function into a context manager. Code before the `yield` statement acts as `__enter__()`; the value yielded is bound to the `as` target; code inside the `finally` block acts as `__exit__()`.

2Architecture Diagram

def manager():
  setup()
  try: yield resource
  finally: cleanup() ---> Guarantees teardown!

3Code Example

Python 3.12
from contextlib import contextmanager
import time

@contextmanager
def execution_timer(label: str):
    start = time.perf_counter()
    try:
        yield
    finally:
        duration = time.perf_counter() - start
        print(f"[{label}] Finished in {duration:.6f}s")

with execution_timer("Data Ingestion Pipeline"):
    total = sum(i for i in range(500_000))
print(f"Calculated sum: {total}")

4Expected Output

[Data Ingestion Pipeline] Finished in 0.015214s
Calculated sum: 124999750000

5Key Takeaways

  • Always wrap the `yield` statement inside a `try...finally` block to guarantee cleanup on exceptions.
  • Eliminates class boilerplate when creating simple resource wrappers.
  • If an exception occurs in the with block, it is re-raised at the `yield` point in the generator.