Python context manager not cleaning up

contextmanager, exception, python, python-2.7, try-except

Solution

You'll need to add exception handling yourself:

@contextmanager
def say_goodbye():
    try:
        yield
    finally:
        print "bye from context manager"

The above ensures the `finally` block always runs regardless of an exception inside the with block. If you want exceptions to be handled you'll need to catch those and possible reraise them:

@contextmanager
def say_goodbye():
    try:
        yield
    except Exception as exc:
        print(exc)
    finally:
        print "bye from context manager"

As the documentation says:

If an unhandled exception occurs in the block, it is reraised inside the generator at the point where the yield occurred. Thus, you can use a try...except...finally statement to trap the error (if any), or ensure that some cleanup takes place.

Also note that `BaseException` is not an `Exception`:

>>> isinstance(BaseException(), Exception)
False

Your own exceptions should inherit from `Exception`, not `BaseException`.

Problem

When I raise any exceptions inside a context manager the cleanup code is not run. For example: ``` from contextlib import contextmanager try: raise BaseException() except BaseException: print "bye from except" @contextmanager def say_goodbye(): yield print "bye from context manager" with say_goodbye(): raise BaseException() ``` Will output: ``` bye from except Traceback (most recent call last): File "", line 15, in BaseException ``` Notice that the try/except properly catches the exception while the with statement does not. Is there something I don't understand about how with statements are supposed to work? You can see the code in a fiddle here: http://pythonfiddle.com/context-manager-failing FYI I'm running python 2.7 on OSX mavericks. Although I've been able to reproduce in many environments so I doubt that has much to do with it.

Original source