What are context managers in Python and how do you implement one with __enter__ and __exit__?
py-mid-003
Your answer
Answer as you would in a real interview — explain your thinking, not just the conclusion.
Model answer
A context manager is an object that defines __enter__ and __exit__ methods, enabling use with the with statement. __enter__ is called on entry and its return value is bound to the as clause variable. __exit__ is called on exit with (exc_type, exc_val, exc_tb) — if it returns True, any exception is suppressed. Context managers guarantee clean-up even when exceptions occur — much safer than try/finally in most cases. The contextlib.contextmanager decorator lets you write a generator-based context manager without a class. Common uses: file handles, database transactions, locks, network connections, timing code sections. The with statement is syntax sugar for calling __enter__/__exit__.
Code example
from contextlib import contextmanager
import time
# Class-based context manager
class Timer:
def __enter__(self):
self._start = time.perf_counter()
return self
def __exit__(self, exc_type, exc_val, exc_tb):
self.elapsed = time.perf_counter() - self._start
return False # do not suppress exceptions
with Timer() as t:
time.sleep(0.1)
print(f"elapsed: {t.elapsed:.3f}s")
# Generator-based with contextlib.contextmanager
@contextmanager
def managed_connection(url: str):
conn = connect(url)
try:
yield conn
except Exception:
conn.rollback()
raise
finally:
conn.close() # always runs
with managed_connection("postgresql://...") as conn:
conn.execute("INSERT INTO orders VALUES (...)")
# Suppress specific exception
from contextlib import suppress
with suppress(FileNotFoundError):
os.remove("tmp.txt")
Follow-up
How would you implement a context manager that both times a code block and suppresses a specific exception type?