ZetCode

Python __enter__ Method

Last modified April 8, 2025

This comprehensive guide explores Python's __enter__ method, the special method used in context managers. We'll cover basic usage, resource management, file handling, database connections, and practical examples.

Basic Definitions

The __enter__ method is part of Python's context manager protocol. It defines what happens at the start of a with statement block.

Key characteristics: it's called when entering the runtime context, returns an object bound to the as variable, and works with __exit__ for clean resource management. It enables the "with" statement functionality.

Basic Context Manager

Here's a simple context manager demonstrating __enter__ and __exit__ working together to manage resources.

basic_context.py
class SimpleContext:
    def __enter__(self):
        print("Entering context")
        return self
    
    def __exit__(self, exc_type, exc_val, exc_tb):
        print("Exiting context")
    
    def show(self):
        print("Inside context")

with SimpleContext() as ctx:
    ctx.show()

This example shows the basic structure of a context manager. __enter__ is called when entering the with block, and __exit__ when leaving. The output shows the sequence of execution.

The __enter__ method returns self, which is assigned to ctx. This allows calling methods on the context manager object.

File Handling Context Manager

A common use of __enter__ is in file handling, where it ensures proper file opening and closing.

file_context.py
class FileHandler:
    def __init__(self, filename, mode):
        self.filename = filename
        self.mode = mode
    
    def __enter__(self):
        self.file = open(self.filename, self.mode)
        return self.file
    
    def __exit__(self, exc_type, exc_val, exc_tb):
        self.file.close()

with FileHandler('example.txt', 'w') as f:
    f.write('Hello, context manager!')

This custom file handler mimics Python's built-in file context manager. __enter__ opens the file and returns the file object.

The __exit__ method ensures the file is closed, even if an exception occurs. This prevents resource leaks and handles cleanup.

Database Connection Context Manager

__enter__ is ideal for managing database connections, ensuring they're properly closed after use.

db_context.py
import sqlite3

class DatabaseConnection:
    def __init__(self, db_name):
        self.db_name = db_name
    
    def __enter__(self):
        self.conn = sqlite3.connect(self.db_name)
        return self.conn
    
    def __exit__(self, exc_type, exc_val, exc_tb):
        self.conn.close()
        if exc_type is not None:
            print(f"Error occurred: {exc_val}")

with DatabaseConnection('test.db') as conn:
    cursor = conn.cursor()
    cursor.execute("CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY, name TEXT)")

This context manager handles SQLite database connections. __enter__ establishes the connection and returns it for use in the with block.

__exit__ closes the connection and optionally handles exceptions. This pattern ensures database resources are properly released.

Timing Context Manager

__enter__ can be used to measure execution time by recording the start time when entering the context.

timer_context.py
import time

class Timer:
    def __enter__(self):
        self.start = time.time()
        return self
    
    def __exit__(self, exc_type, exc_val, exc_tb):
        self.end = time.time()
        print(f"Elapsed time: {self.end - self.start:.2f} seconds")

with Timer():
    time.sleep(1)
    sum(range(1000000))

This timer context manager records the start time in __enter__ and calculates the elapsed time in __exit__. It demonstrates a non-resource use case.

The context manager doesn't need to return a useful object in this case, so it just returns self. The timing logic is entirely in the enter/exit.

Context Manager with State

__enter__ can manage complex state setup and teardown, as shown in this temporary directory example.

tempdir_context.py
import os
import tempfile
import shutil

class TemporaryDirectory:
    def __enter__(self):
        self.dirname = tempfile.mkdtemp()
        return self.dirname
    
    def __exit__(self, exc_type, exc_val, exc_tb):
        shutil.rmtree(self.dirname)

with TemporaryDirectory() as tempdir:
    print(f"Created temp directory: {tempdir}")
    with open(os.path.join(tempdir, 'test.txt'), 'w') as f:
        f.write('Temporary file content')

This context manager creates a temporary directory in __enter__ and returns its path. __exit__ cleans up by removing the directory.

The example shows how __enter__ can handle complex setup operations while ensuring proper cleanup, even if exceptions occur during execution.

Best Practices

Source References

Author

My name is Jan Bodnar, and I am a passionate programmer with extensive programming experience. I have been writing programming articles since 2007. To date, I have authored over 1,400 articles and 8 e-books. I possess more than ten years of experience in teaching programming.

List all Python tutorials.