peps: Elaborate transaction() manager example (Chris A).
![](https://secure.gravatar.com/avatar/8ac615df352a970211b0e3d94a307c6d.jpg?s=120&d=mm&r=g)
https://hg.python.org/peps/rev/4803b0829533 changeset: 5624:4803b0829533 user: Guido van Rossum <guido@python.org> date: Fri Nov 28 17:26:33 2014 -0800 summary: Elaborate transaction() manager example (Chris A). files: pep-0479.txt | 31 ++++++++++++++++++++++--------- 1 files changed, 22 insertions(+), 9 deletions(-) diff --git a/pep-0479.txt b/pep-0479.txt --- a/pep-0479.txt +++ b/pep-0479.txt @@ -44,26 +44,39 @@ existent". Unfortunately while intentional use is rare, it is easy to stumble on these cases by accident:: + import contextlib + @contextlib.contextmanager def transaction(): - begin() + print('begin') try: yield from do_it() except: - rollback() + print('rollback') raise else: - commit() - + print('commit') + def do_it(): - initial_preparations() - yield - finishing_touches() + print('Refactored preparations') + yield # Body of with-statement is executed here + print('Refactored finalization') + + def gene(): + for i in range(2): + with transaction(): + yield i + # return + raise StopIteration # This is wrong + print('Should not be reached') + + for i in gene(): + print('main: i =', i) Here factoring out ``do_it`` into a subgenerator has introduced a subtle bug: if the wrapped block raises ``StopIteration``, under the -current behavior ``do_it`` will fail but report success by returning -normally, causing the failed transaction to be committed! Similarly +current behavior this exception will be swallowed by the context +manager; and, worse, the finalization is silently skipped! Similarly problematic behavior occurs when an ``asyncio`` coroutine raises ``StopIteration``, causing it to terminate silently. -- Repository URL: https://hg.python.org/peps
participants (1)
-
guido.van.rossum