Писал ли ты свои контекстные менеджеры в Python
Что проверяют
Понимаете ли вы протокол with изнутри, а не как магию, и умеете ли гарантировать освобождение ресурса при исключении. Это проверка на аккуратность: код, где файл или блокировка закрываются только на счастливом пути, ломается в проде, а не в тестах.
Как отвечать
Скажите, что писали, и назовите оба способа. Классовый: метод __enter__ возвращает объект, который попадёт в as, а __exit__ получает тип, значение и трассировку исключения и вызывается в любом случае. Короткий способ через генератор:
from contextlib import contextmanager
@contextmanager
def transaction(conn):
try:
yield conn
conn.commit()
except Exception:
conn.rollback()
raiseДальше назовите реальные применения: транзакция базы с откатом, временный каталог, подмена настроек в тесте, захват блокировки, замер времени, временное повышение уровня логирования.
Важная деталь, которую спрашивают следом: если __exit__ возвращает истинное значение, исключение считается обработанным и наружу не выходит. По умолчанию возвращайте None. Полезно упомянуть contextlib.suppress и closing, ExitStack для переменного числа ресурсов и асинхронную пару __aenter__ и __aexit__ для async with.
Где спотыкаются
Пишут очистку после yield без try/finally. При исключении внутри блока генератор до этой строки не доходит, ресурс остаётся висеть, и именно это обычно проверяют дополнительным вопросом.
Второе: возвращают True из __exit__, чтобы не падало. Так проглатываются все исключения блока, включая чужие и не относящиеся к делу, а ошибка всплывает далеко от места возникновения в виде пустого результата.
Третье: объясняют контекстный менеджер через фразу «он просто закрывает файл». Смысл шире: это гарантия парного действия, вход и выход, причём выход выполняется и при return, и при исключении, и при break внутри блока.