Complete worked example
python
from contextlib import ExitStack, contextmanager
def inspect_example(names, fail):
events = []
@contextmanager
def resource(name):
events.append('open:' + name)
try:
yield name
finally:
events.append('close:' + name)
try:
with ExitStack() as stack:
acquired = [stack.enter_context(resource(name)) for name in names]
if fail:
raise ValueError('controlled body failure')
events.append('body:' + str(len(acquired)))
except ValueError:
events.append('caught')
return events- Reasoning
- For names a and b, acquisition appends open:a and open:b. The normal body records that two resources were acquired. Leaving the with statement closes b before a. On a deliberate ValueError, the same exits run before the outer handler appends caught.