TIL you can write your own functions to use in a python with statement. These functions are called context managers. A context manager is a simple way to wrap a try/except/finally block in a reusable function.

Writing your own context manager is simple.

from contextlib import contextmanager

@contextmanager
def random_number():
    """ https://xkcd.com/221/ """
    try:
        # do any setup
        yield 4 # Yielded objects can be accessed from the `var` after the `as` keyword
    except:
        # handle any errors
        pass
    finally:
        # Clean up here (e.g. close db connections or open files)
        pass

## Call the context manager like this
with random_number() as n:
    # do something with `n`
    print(n)

PEP-343 has some other context manager examples.