Skip to main content

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.contextmanager decorator 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)
  • ExitStack manages dynamic numbers of context managers.
  • contextlib.AsyncExitStack (future concurrency cluster) supports async resources.

Next up in your learning path