Context managers e o `with`
Pergunta
O que o `with` faz em Python e como você escreve um context manager?
Resposta esperada
`with recurso() as r:` garante setup e teardown em torno de um bloco, mesmo se o bloco lançar exceção — o padrão pra arquivos, conexões, locks, transações, timers. Um objeto vira context manager implementando `__enter__` (roda na entrada, o retorno vira o `as r`) e `__exit__(exc_type, exc, tb)` (roda na saída, sempre — recebe a exceção se houve, e pode suprimi-la retornando `True`). Forma mais enxuta: o decorator `@contextlib.contextmanager` sobre uma função geradora — o código antes do `yield` é o enter, o `yield` entrega o recurso, o código depois (idealmente num `finally`) é o exit. Vantagem sobre `try/finally` manual espalhado: o cleanup fica junto da aquisição, num lugar, e o call site fica limpo. `contextlib.ExitStack` compõe vários dinamicamente.
Por que perguntam isso
Pergunta pleno de Python. Sinal bom: conhecer o `@contextmanager` com gerador e `__exit__` podendo suprimir a exceção.