🐍 Python - Context Managers
Context managers are simplified but powerful
try/finally pattern. Context managers need to implement
__exit__. Exit method will be performed after any exceptions,
return or even
sys.exit(). You use context managers by using
class Greeting: def __init__(self, text: str) -> None: self.text: str = text def __enter__(self) -> str: return self.text def __exit__(self, exc_type, exc_val, exc_tb) -> None: print('exit') with Greeting('hello') as g: assert g == 'hello' # => exit
contextlib has a helper decorator for turning a generator to a context manager.
from contextlib import contextmanager, closing def greeting(text: str) -> str: try: yield text finally: print('exit') with greeting('hello') as g: assert g == 'hello' # => exit # also, if we would yield a connection, a file or something else closeable, # you can do the following so closing is done automatically # when value goes out of scope # with closing(connection): # yield connection
The same context manager instance can be used multiple times to pass on state.
class Indenter: def __init__(self, amount: int) -> None: self.level = 0 self.amount = amount def __enter__(self) -> 'Indenter': self.level += 1 return self def __exit__(self, exc_type, exc_val, exc_tb) -> None: self.level -= 1 def echo(self, text: str) -> None: print(' ' * (self.level * self.amount) + text) with Indenter(4) as indent: indent.echo('hi!') with indent: indent.echo('hello') with indent: indent.echo('bonjour') indent.echo('hey') # => hi! # => hello # => bonjour # => hey
- Python Tricks The Book, Dan Bader
- Fluent Python, Luciano Ramalho