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
withstatement to manage resources automatically - Create custom context managers with the
contextlibmodule - 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
@contextmanagerdecorator 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