Code Snippets
/

Custom Context Manager via contextlib

Custom Context Manager via contextlib

`@contextlib.contextmanager` turns a generator into a context manager: code before the `yield` is the setup, the yielded value is bound by `as`, and code after the `yield` is the teardown. It removes most of the class boilerplate when you do not need shared state. This entry covers the basic pattern, exception handling with try/finally, and `contextlib.suppress` as a one-liner.

Python
Medium
3 snippets
py-context-managers
py-decorators
py-standard-library

968 views

17

from contextlib import contextmanager

@contextmanager
def temporary_setting(settings, key, value):
    """Set settings[key] for the duration of the with-block, then restore."""
    original = settings.get(key)
    had_key = key in settings
    settings[key] = value
    try:
        yield settings  # whatever you yield is bound by `as`
    finally:
        if had_key:
            settings[key] = original
        else:
            settings.pop(key, None)

config = {'log_level': 'INFO'}

with temporary_setting(config, 'log_level', 'DEBUG') as cfg:
    print('inside:', cfg['log_level'])  # DEBUG

print('after :', config['log_level'])    # INFO  (restored)

with temporary_setting(config, 'feature_x', True):
    print('inside:', config.get('feature_x'))  # True

print('after :', config.get('feature_x'))      # None (key removed)

The generator runs once: code before yield is the __enter__ body, the yielded object is bound by as, and code after yield is the __exit__ body. Wrapping the post-yield code in try / finally is mandatory when teardown must run on exceptions too: without it, an exception from the body skips the cleanup. The decorator handles the boilerplate of building a class with __enter__ and __exit__, so the implementation reads top-to-bottom like normal code. Use this pattern for stateless, run-once setup-and-teardown helpers.