Elaborate transaction() manager example (Chris A).
This commit is contained in:
parent
a6b3c8b1f7
commit
90addf57a2
31
pep-0479.txt
31
pep-0479.txt
|
@ -44,26 +44,39 @@ limitation, but notes that "use cases for these [are] rare to non-
|
|||
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.
|
||||
|
||||
|
|
Loading…
Reference in New Issue