Phase 11 of 25 · Topic 11.2

Context Manager Protocol (__enter__ & __exit__)

1Concept

The Context Manager protocol automates resource acquisition and release via the `with` statement. `__enter__()` acquires the resource and binds it to the `as` target; `__exit__(exc_type, exc_val, exc_tb)` guarantees release, even if exceptions occur. Returning `True` from `__exit__` suppresses the exception.

2Architecture Diagram

with ManagedResource() as res:
  [ Executes __enter__() ] ---> [ Work inside block ] ---> [ Executes __exit__() guaranteed! ]

3Code Example

Python 3.12
class ManagedDatabaseConnection:
    def __init__(self, db_url: str):
        self.db_url = db_url

    def __enter__(self):
        print(f"1. Connected to database: {self.db_url}")
        return self

    def query(self, sql: str):
        print(f"2. Executing: {sql}")

    def __exit__(self, exc_type, exc_val, exc_tb):
        print("3. Releasing database connection back to pool.")
        if exc_type:
            print(f"[Handled Exception inside Context Manager]: {exc_val}")
        return False # Do not suppress exception

with ManagedDatabaseConnection("postgres://cluster.corp:5432") as conn:
    conn.query("SELECT * FROM accounts;")

4Expected Output

1. Connected to database: postgres://cluster.corp:5432
2. Executing: SELECT * FROM accounts;
3. Releasing database connection back to pool.

5Key Takeaways

  • `__exit__` receives exception details if an error occurs inside the `with` block.
  • Returning `True` from `__exit__` suppresses the exception; returning `False` allows it to propagate.
  • Standard practice for files, database transactions, and threading locks.