Python etc / @contextmanager decorator

@contextmanager decorator

Generators are one of the most influential Python mechanics. They have many uses, and one of them is to create context managers easily. Usually, you have to manually define __enter__ and __exit__ magic methods, but @contextmanager decorator from contextlib makes it far more convenient:

from contextlib import contextmanager

@contextmanager
def atomic():
    print('BEGIN')

    try:
        yield
    except Exception:
        print('ROLLBACK')
    else:
        print('COMMIT')

Now atomic is a context manager that can be used like this:

In : with atomic():
...:     print('ERROR')
...:     raise RuntimeError()
...:
BEGIN
ERROR
ROLLBACK

Additionally, the @contextmanager magic allows to use it as a decorator as well as a context manager:

In : @atomic()
...: def ok():
...:     print('OK')
...:
In : ok()
...:
BEGIN
OK
COMMIT