Context Managers & `with` Statements
Advanced Abstractions
Context Managers
`with` statements prevent leaks and keep setup/teardown paired. Build your own context managers for locks, transactions, and temporary overrides.
Protocol
class temporary_env:
def __init__(self, key, value):
self.key = key
self.value = value
def __enter__(self):
self.original = os.getenv(self.key)
os.environ[self.key] = self.value
return self.value
def __exit__(self, exc_type, exc, tb):
if self.original is None:
os.environ.pop(self.key, None)
else:
os.environ[self.key] = self.original
return False # propagate errors
contextlib helpers
contextlib.contextmanagerdecorator turns a generator into a context manager.
from contextlib import contextmanager
@contextmanager
def timed():
start = time.perf_counter()
yield
logger.info("elapsed %.3f", time.perf_counter() - start)
ExitStackmanages dynamic numbers of context managers.contextlib.AsyncExitStack(future concurrency cluster) supports async resources.