Understanding Context Managers and the With Statement in Python

Example 1: Basic Mechanics

Consider the following class definition and its usage:

class ResourceHandler:
    def __init__(self):
        print('Object initialized')

    def __enter__(self):
        print('Setup phase')

    def __exit__(self, exc_type, exc_value, traceback):
        print('Teardown phase')

resource = ResourceHandler()

with resource:
    print('Main logic running')

Output:

Object initialized
Setup phase
Main logic running
Teardown phase

When an object defines both __enter__ and __exit__ methods, it is considered a context manager. The with construtc interacts with this protocol by executing the __enter__ method before the block starts and the __exit__ method immediately after the block finishes.

Example 2: Exception Handling

Context managers integrate tightly with exception handling. Observe the behavior when an error occurs inside the block:

class SafeHandler:
    def __init__(self):
        print('Ready')

    def __enter__(self):
        print('Start')

    def __exit__(self, exc_type, exc_value, traceback):
        print('Cleanup')
        # return True

handler = SafeHandler()

with handler:
    raise ValueError("Something went wrong")
    print('This will not print')

If the __exit__ method returns a truthy value (like True), the exception is suppressed. If it returns None or False (the default), the exception propagates after cleanup. This mimics the behavior of a try...except...finally block but with cleaner syntax.

Example 3: The 'as' Keyword

The __enter__ method can return a value that is bound to a variable using the as keyword:

class Connection:
    def __enter__(self):
        print('Opening connection')
        return self  # The returned value is assigned to 'conn'

    def __exit__(self, exc_type, exc_value, traceback):
        print('Closing connection')

with Connection() as conn:
    print(f'Using connection: {conn}')

If __enter__ does not explicitly return a value, the target variable (e.g., conn) will be None. The target can be a single varible or a tuple enclosed in parentheses.

Example 4: File Operations

The most common use case is managing file streams. The built-in open() function returns a file object that acts as a context manager.

with open("/tmp/data.txt") as file_handle:
    content = file_handle.read()

This ensures the file is automatically closed when the block exits, even if an error occurs. Without with, you would need a manual try/finally structure:

file_handle = open('data.txt')
try:
    content = file_handle.read()
finally:
    file_handle.close()

Several standard library modules support this protocol, including threading and decimal.

Common Context Managers

Besides files, other standard tools that implement the context management protoclo include:

  • threading.Lock
  • threading.RLock
  • threading.Condition
  • threading.Semaphore
  • decimal.Context

Tags: python Context Manager with statement __enter__ __exit__

Posted on Tue, 03 Nov 2026 16:06:26 +0000 by beezza