Python25 min read

Python Context Managers Advanced

Build reliable resource-handling with advanced context managers: custom __enter__/__exit__, error suppression, and ExitStack for multiple resources.

David Miller
July 25, 2025
6.7k272

You already know with open(...) closes files automatically.

      A context manager guarantees:
      - setup happens before your code runs
      - cleanup happens after your code finishes
      Even if an exception happens.
      
      This is critical in production code.
      
      ## Class-based context manager (Timer)
      
      ```python
      import time
      
      class Timer:
          def __enter__(self):
              self.start = time.time()
              return self
      
          def __exit__(self, exc_type, exc_val, exc_tb):
              end = time.time()
              print(f"Time taken: {end - self.start:.4f}s")
      
      with Timer():
          total = sum(i for i in range(1_000_000))
      ```
      
      ## Handling exceptions inside context managers
      
      Sometimes you want to catch errors and continue.
      
      ```python
      class SafeDivision:
          def __enter__(self):
              return self
      
          def __exit__(self, exc_type, exc_val, exc_tb):
              if exc_type:
                  print("Handled error:", exc_val)
                  return True  # suppress exception
              return False
      
      with SafeDivision():
          x = 10 / 0
      
      print("Program continues...")
      ```
      
      ## Using ExitStack (manage multiple resources)
      
      ExitStack is useful when you open dynamic number of resources.
      
      ```python
      from contextlib import ExitStack
      
      files = ["a.txt", "b.txt", "c.txt"]
      
      with ExitStack() as stack:
          handles = [stack.enter_context(open(name, "w")) for name in files]
          for h in handles:
              h.write("Hello\n")
      ```
      
      All files are closed properly, even if something fails halfway.
      
      ## Using contextlib to build a context manager (cleaner)
      
      ```python
      from contextlib import contextmanager
      import time
      
      @contextmanager
      def timer():
          start = time.time()
          try:
              yield
          finally:
              end = time.time()
              print(f"Time taken: {end - start:.4f}s")
      
      with timer():
          sum(i for i in range(1_000_000))
      ```
      
      ## Graph: context manager lifecycle
      
      ```mermaid
      flowchart LR
        A[Enter with-block] --> B[__enter__ setup]
        B --> C[Run your code]
        C --> D[__exit__ cleanup]
        C --> E[Exception occurs]
        E --> D
      ```
      
      ## Key points
      
      - Context managers guarantee cleanup
      - __exit__ can suppress exceptions (return True)
      - ExitStack helps manage many resources safely
      
#Python#Advanced#Context Managers