0
0
PythonHow-ToBeginner · 3 min read

How to Create Custom Context Manager in Python Easily

In Python, you can create a custom context manager by defining a class with __enter__ and __exit__ methods or by using the contextlib module with a generator function decorated by @contextmanager. These methods help manage resources by setting up and cleaning up automatically when used with the with statement.
📐

Syntax

A custom context manager class must have two special methods:

  • __enter__(self): Runs when entering the with block. It can return a value used inside the block.
  • __exit__(self, exc_type, exc_value, traceback): Runs when exiting the block. It handles cleanup and exceptions.

Alternatively, use @contextmanager decorator from contextlib on a generator function that yields once.

python
class MyContextManager:
    def __enter__(self):
        # Setup code here
        return self

    def __exit__(self, exc_type, exc_value, traceback):
        # Cleanup code here
        pass

from contextlib import contextmanager

@contextmanager
def my_context():
    # Setup code
    yield
    # Cleanup code
💻

Example

This example shows a custom context manager class that prints messages when entering and exiting the with block. It also handles exceptions gracefully.

python
class CustomContext:
    def __enter__(self):
        print("Entering the context")
        return "Resource"

    def __exit__(self, exc_type, exc_value, traceback):
        if exc_type:
            print(f"An exception occurred: {exc_value}")
        print("Exiting the context")
        return True  # Suppress exception

with CustomContext() as resource:
    print(f"Inside with block using {resource}")
    # Uncomment next line to test exception handling
    # raise ValueError("Oops")
Output
Entering the context Inside with block using Resource Exiting the context
⚠️

Common Pitfalls

Common mistakes when creating custom context managers include:

  • Not implementing both __enter__ and __exit__ methods in a class.
  • Forgetting to return a value from __enter__ if needed inside the with block.
  • Not handling exceptions properly in __exit__, which can cause unexpected crashes.
  • In @contextmanager functions, forgetting to use yield exactly once.

Example of a wrong and right way:

python
class WrongContext:
    def __enter__(self):
        print("Enter")
    # Missing __exit__ method

class RightContext:
    def __enter__(self):
        print("Enter")
        return self
    def __exit__(self, exc_type, exc_value, traceback):
        print("Exit")

with RightContext():
    print("Inside")
Output
Enter Inside Exit
📊

Quick Reference

Remember these key points when creating custom context managers:

  • Use __enter__ to set up and optionally return a resource.
  • Use __exit__ to clean up and handle exceptions.
  • Use @contextmanager decorator for simpler generator-based context managers.
  • Always test your context manager with and without exceptions.

Key Takeaways

Define __enter__ and __exit__ methods to create a class-based context manager.
Use the @contextmanager decorator for simpler generator-based context managers.
Always handle exceptions in __exit__ to avoid crashes inside with blocks.
Return a value from __enter__ if you want to use it inside the with block.
Test your context manager both with normal execution and exceptions.