Back to Blog

Python Context Managers Explained - with Statement, __enter__, __exit__ & contextlib | Tutorial #25

Sandy LaneSandy Lane

Video: Python Context Managers Explained - with Statement, __enter__, __exit__ & contextlib | Tutorial #25 by Taught by Celeste AI - AI Coding Coach

Watch full page →

Python Context Managers Explained - with Statement, __enter__, __exit__ & contextlib

Context managers in Python simplify resource management by ensuring setup and cleanup actions are automatically handled. Using the with statement, you can manage files, timers, database connections, and more, while safely handling exceptions. This tutorial covers both class-based and generator-based context managers, including the powerful contextlib utilities.

Code

import time
from contextlib import contextmanager

# Class-based context manager for timing code execution
class Timer:
  def __enter__(self):
    self.start = time.time()  # Record start time
    return self               # Return self to use inside with-block

  def __exit__(self, exc_type, exc_val, exc_tb):
    elapsed = time.time() - self.start
    print(f"Elapsed: {elapsed:.4f}s")  # Print elapsed time
    return False  # Do not suppress exceptions

# Generator-based context manager for simulating a database connection
@contextmanager
def database(name):
  db = {"name": name, "connected": True}  # Setup: connect to database
  print(f"Connected to database '{name}'")
  yield db  # Provide the database object to the with-block
  db["connected"] = False  # Cleanup: disconnect
  print(f"Disconnected from database '{name}'")

# Example usage:
with Timer():
  time.sleep(1)  # Simulate a time-consuming operation

with database("MyDB") as db:
  print(f"Using database: {db['name']}, connected = {db['connected']}")

Key Points

  • The with statement automatically calls __enter__ at the start and __exit__ at the end of a block.
  • Class-based context managers implement __enter__ and __exit__ methods to manage resources and handle exceptions.
  • The @contextmanager decorator lets you write context managers as generator functions using yield to separate setup and cleanup.
  • Context managers ensure resources like files, timers, or database connections are properly cleaned up, even if errors occur.
  • Returning False from __exit__ propagates exceptions, while returning True suppresses them.