I think I've read that exceptions inside a with
do not allow __exit__
to be call correctly. If I am wrong on this note, pardon my ignorance.
So I have some pseudo code here, my goal is to use a lock context that upon __enter__
logs a start datetime and returns a lock id, and upon __exit__
records an end datetime and releases the lock:
def main():
raise Exception
with cron.lock() as lockid:
print('Got lock: %i' % lockid)
main()
How can I still raise errors in addition to existing the context safely?
Note: I intentionally raise the base exception in this pseudo-code as I want to exit safely upon any exception, not just expected exceptions.
Note: Alternative/standard concurrency prevention methods are irrelevant, I want to apply this knowledge to any general context management. I do not know if different contexts have different quirks.
PS. Is the finally
block relevant?
Best Solution
The
__exit__
method is called as normal if the context manager is broken by an exception. In fact, the parameters passed to__exit__
all have to do with handling this case! From the docs:So you can see that the
__exit__
method will be executed and then, by default, any exception will be re-raised after exiting the context manager. You can test this yourself by creating a simple context manager and breaking it with an exception:When you run this code, you should see everything you want (might be out of order since
print
tends to end up in the middle of tracebacks):