Reputation: 2348
I'm using sqlalchemy to create a transaction. I'm using with
to take advantage of the auto commit and rollback:
with session.begin():
do_stuff()
If an exception is raised, is there anyway to propagate that exception after the auto rollback?
Upvotes: 0
Views: 258
Reputation: 530882
If any exception is raised during the body of a with
statement, the __exit__
method is immediately called with that exception as an argument. It is up to __exit__
to then decide whether the exception has been properly handled (by returning a truthy value) or whether it should be re-raised after __exit__
completes (by returning a non-truthy value).
SessionTransaction.__exit__
only returns None
, which indicates that any exception that may have been raised in the body of the with
statement will be raised again.
Note that since the "default" return value of any function is None
,
the default behavior of __exit__
is to propagate any exceptions. No user-level code is expected to call __exit__
explicitly or look at its return value, so you really have to do out of your way to return a truthy value and suppress an expression.
Also note the description of the with
statement's semantics:
The following code:
with EXPRESSION as TARGET: SUITE
is semantically equivalent to:
manager = (EXPRESSION) enter = type(manager).__enter__ exit = type(manager).__exit__ value = enter(manager) hit_except = False try: TARGET = value SUITE except: hit_except = True if not exit(manager, *sys.exc_info()): raise finally: if not hit_except: exit(manager, None, None, None)
The __exit__
method is called under one of two mutually exclusive conditions:
except
clause. If it returns false, the caught exception is re-raised.finally
block. hit_except
is ensures that exit
is not called twice
if exit
itself raises an exception in the except
block.Upvotes: 1
Reputation: 780723
You shouldn't need to do anything special.
Context managers created using with
are roughly equivalent to:
try:
context initialization
do_stuff()
finally:
contact cleanup
Unlike an except:
clause, finally:
doesn't block propagation of the exception. It executes the statements and then continues propagation.
Upvotes: 0