pythonintermediate

Custom Context Manager

Context managers for resource management using both class-based and decorator approaches with error handling.

python
import time
import logging
from contextlib import contextmanager
from typing import Generator

logger = logging.getLogger(__name__)


# Class-based context manager
class DatabaseConnection:
    def __init__(self, connection_string: str):
        self.connection_string = connection_string
        self.connection = None

    def __enter__(self):
        logger.info(f"Connecting to {self.connection_string}")
        self.connection = self._connect()
        return self.connection

    def __exit__(self, exc_type, exc_val, exc_tb):
        if self.connection:
            if exc_type:
                logger.error(f"Rolling back due to: {exc_val}")
                self.connection.rollback()
            else:
                self.connection.commit()
            self.connection.close()
            logger.info("Connection closed")
        return False  # Don't suppress exceptions

    def _connect(self):
        # Replace with actual connection logic
        return type("Conn", (), {"commit": lambda s: None, "rollback": lambda s: None, "close": lambda s: None})()


# Decorator-based context manager
@contextmanager
def timer(label: str) -> Generator[None, None, None]:
    start = time.perf_counter()
    try:
        yield
    finally:
        elapsed = time.perf_counter() - start
        logger.info(f"{label}: {elapsed:.3f}s")


# Usage:
# with DatabaseConnection("postgresql://localhost/mydb") as conn:
#     conn.execute("SELECT 1")
#
# with timer("data processing"):
#     process_large_dataset()

Use Cases

  • Database connection management
  • File handle cleanup
  • Performance measurement

Tags

Related Snippets

Similar patterns you can reuse in the same workflow.