Question presented to candidate:
"You write with open(path) as f: all the time. What is actually going on there? Explain what a context manager is, how you would write your own, and what happens when the code inside the block raises."
What a strong answer should cover:
- A context manager is an object that sets something up on entry and is guaranteed to tear it down on exit; the
withstatement drives it, and it is a structured replacement fortry/finally. - The protocol:
__enter__()runs first and its return value is whatasbinds;__exit__(exc_type, exc_value, traceback)always runs, on normal exit,return,breakor an exception. - Exception handling:
__exit__receives the exception, and a truthy return value suppresses it; returningNone/Falselets it propagate. - Two ways to write one: a class with
__enter__/__exit__, or a generator decorated withcontextlib.contextmanager(the code afteryieldmust sit infinallyto run on errors). - Real uses and stdlib helpers: files, locks, transactions, temporary state;
contextlib.suppress,nullcontext,closing,ExitStack, plusasync withfor async managers. - A CPython detail:
__enter__/__exit__are looked up on the type, not the instance, and in 3.11 the bytecode isBEFORE_WITHplusWITH_EXCEPT_START.
Code / implementation expected: Yes โ a small class-based manager and the same thing written with @contextmanager, showing what happens when the body raises.