ExitStack manages multiple context managers dynamically.
1from contextlib import ExitStack23# Open multiple files4with ExitStack() as stack:5 files = [6 stack.enter_context(open(f"file{i}.txt"))7 for i in range(5)8 ]9 for f in files:10 process(f)11 # All files closed automatically1213# Dynamic context managers14from contextlib import contextmanager1516@contextmanager17def managed_resource(name):18 print(f"Acquiring {name}")19 yield name20 print(f"Releasing {name}")2122with ExitStack() as stack:23 resources = []24 for name in ["db", "cache", "queue"]:25 resource = stack.enter_context(managed_resource(name))26 resources.append(resource)27 process(resources)28 # All resources released in reverse order2930# Callbacks31with ExitStack() as stack:32 stack.callback(print, "Cleanup 1")33 stack.callback(print, "Cleanup 2")34 # On exit: prints "Cleanup 2" then "Cleanup 1"
Use cases: