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.