Using Context Managers in Python 2026

Writing Functions Mar 16, 2026

Using Context Managers in Python 2026

Context managers are one of Python’s most elegant and powerful features. They ensure resources are properly acquired and released, making your code safer, cleaner, and more reliable. In 2026, mastering context managers is considered essential for writing professional-grade functions.

TL;DR — Key Takeaways 2026

  • Use the with statement to manage resources automatically
  • Create custom context managers with the contextlib module
  • Always use context managers for files, database connections, locks, etc.
  • They help prevent resource leaks and make code more readable

1. Basic Usage


# Demo file so this example runs as-is
with open("data.txt", "w") as f:
    f.write("first line\nsecond line\n")

# Traditional way (error-prone)
file = open("data.txt", "r")
try:
    content = file.read()
finally:
    file.close()

# Modern, clean way with context manager
with open("data.txt", "r") as file:
    content = file.read()
# File is automatically closed here

2. Creating Custom Context Managers


from contextlib import contextmanager

@contextmanager
def timer(name: str):
    """Context manager to time code blocks."""
    import time
    start = time.perf_counter()
    try:
        yield
    finally:
        elapsed = time.perf_counter() - start
        print(f"{name} took {elapsed:.4f} seconds")

def run_expensive_query():   # stand-in for a real database query
    return sum(range(1_000_000))

# Usage
with timer("Database query"):
    result = run_expensive_query()

# Class-based context manager
class DatabaseConnection:
    def __enter__(self):
        self.conn = connect_to_db()
        return self.conn
    
    def __exit__(self, exc_type, exc_val, exc_tb):
        self.conn.close()

3. Best Practices in 2026

  • Use context managers for all resources that need cleanup (files, sockets, locks, database connections)
  • Prefer the @contextmanager decorator for simple cases
  • Use class-based context managers when you need more complex state management
  • Always handle exceptions properly in __exit__
  • Combine multiple context managers using contextlib.ExitStack

What a Context Manager Guarantees

A context manager is an object that sets something up when a with block starts and cleans it up when the block ends. Python calls its __enter__ method at the start and its __exit__ method at the end, and __exit__ runs even if the block raises an exception.

This guarantee is the main reason to use with. Files are closed, locks are released, database transactions are committed or rolled back and temporary settings are restored, whatever happens inside the block. The equivalent try/finally code is longer and easy to get wrong.

The standard library includes many ready-made context managers: open() for files, threading.Lock for locks, decimal.localcontext for precision, contextlib.suppress for ignoring a specific exception, and tempfile.TemporaryDirectory for scratch folders that delete themselves.

Using these built-in managers is often enough. Writing your own makes sense when your code has a set-up and tear-down pair that repeats in many places.

Worked Example: Built-In Context Managers at Work

We use three standard context managers and check that each cleans up after itself.

import os
import tempfile
from contextlib import suppress

with tempfile.TemporaryDirectory() as folder:
    path = os.path.join(folder, "notes.txt")
    with open(path, "w") as f:
        f.write("hello")
    print("file closed:", f.closed)
print("folder still exists:", os.path.exists(folder))

with suppress(FileNotFoundError):
    os.remove("does-not-exist.txt")
print("missing file ignored")

The file is closed as soon as its block ends, the temporary folder is deleted after the outer block, and suppress silently ignores the FileNotFoundError. No explicit close or cleanup call was needed.

Practical Tips

Look for set-up and tear-down pairs in your own code, such as connect and close, start and stop, or lock and unlock. Each pair is a candidate for a with statement.

Keep the body of a with block short. Long blocks hold the resource open longer than needed, which matters for files, locks and database connections.

contextlib.closing turns any object with a close method into a context manager.

Common Mistakes

  • Opening files without with and forgetting to close them on errors.
  • Using suppress(Exception), which hides real bugs.
  • Returning a resource from inside a with block and using it after it closed.
  • Writing a custom manager when a standard one exists.

Quick Summary

  • with guarantees clean-up, even on errors.
  • __enter__ sets up, __exit__ tears down.
  • The standard library has many managers.
  • Write your own for repeated set-up pairs.

Conclusion

Context managers are one of Python’s greatest features for writing safe and clean code. In 2026, using the with statement and creating custom context managers should be your default approach whenever you work with resources that need proper setup and teardown.

Next steps:

  • Review your functions and replace manual resource management with context managers

Related Tutorials

Share:
Last updated: March 2026
Built-in Functions in Python 2026 str() in Python 2026: String Conversion + Modern Formatting & Best Practices memoryview with JAX in Python 2026: Zero-Copy NumPy → JAX Array Interop + Efficient ML Examples memoryview with TensorFlow in Python 2026: Zero-Copy NumPy → Tensor Interop + GPU Pinning & ML Examples memoryview with TensorFlow in Python 2026: Zero-Copy NumPy → Tensor Interop + ML Examples memoryview with NumPy & PyTorch in Python 2026: Zero-Copy Views, Efficient Slicing & ML Interop Examples memoryview with NumPy in Python 2026: Zero-Copy Views, Efficient Slicing & Real ML Examples memoryview() in Python 2026: Zero-Copy Magic for Large Binary Data + Real Examples import() in Python 2026: How It Works, Security Risks & Modern Alternatives (importlib) zip() in Python 2026: How to Use It, strict=True Behavior & Real-World Examples vars() in Python 2026: Accessing Object Namespace + Modern Introspection Patterns type() in Python 2026: Dynamic Type Inspection & Object Creation + Modern Patterns tuple() in Python 2026: Immutable Sequences + Modern Patterns & Best Practices super() in Python 2026: Method Resolution & Modern Inheritance Patterns sum() in Python 2026: Summing Iterables + Modern Numeric Patterns & Best Practices staticmethod() in Python 2026: Static Methods, Utility Functions & Modern Best Practices sorted() in Python 2026: Sorting Iterables + Modern Patterns & Best Practices slice() in Python 2026: Creating Slice Objects + Modern Patterns & Best Practices setattr() in Python 2026: Dynamic Attribute Setting + Modern Patterns & Safety set() in Python 2026: Mutable Sets Creation + Modern Patterns & Best Practices