Python Module 7
Errors, exceptions and context managers interview questions
Interview questions on errors, exceptions and context managers: warm-ups, then what each harder question tests and how a good answer starts.
Warm-up questions
Short questions with short answers, each answered in full.
-
Fresher
In a
trystatement withexcept,elseandfinallyclauses, which clauses run when thetryblock succeeds, and which run when it raises an exception that oneexceptclause handles?Answered in the lesson Handling exceptions with try and except
-
Fresher to mid
Why does a library usually define one base exception class, such as
BookingError, with more specific classes under it?Answered in the lesson Raising exceptions and custom error classes
-
Fresher to mid
What is the difference between an exception's
__cause__and its__context__?Answered in the lesson Exception chaining, notes and tracebacks
-
Mid
What does
except* ValueErrordo with anExceptionGroupthat holds aValueErrorand aTypeError? -
Fresher to mid
What does the
withstatement guarantee, and what changes when__exit__()returnsTrue?Answered in the lesson Context managers and the with statement
-
Fresher to mid
Why does a
DeprecationWarningthat a library issues often go unseen by the developers who call it, and who does see it?Answered in the lesson Warnings, assertions and development mode
-
Fresher to mid
What exit status should a command-line program return, and why does it matter?
Answered in the lesson Designing error handling for real programs
Questions with model answers
What each question tests, the first step of a good answer and the follow-ups to expect.
-
Fresher to mid
A nightly import runs
try: import_record(r)with a bareexcept: continuefor each of 200,000 records. Operators cannot stop it with Ctrl-C, and some nights it reports success while 40 % of the records are missing. Explain both symptoms and rewrite the loop.- What it tests
- What a bare except catches, why broad handlers turn bugs into silent data loss, and how to skip bad records without hiding failures.
- First step
- Start with the hierarchy: a bare except matches every exception, KeyboardInterrupt and SystemExit included, so Ctrl-C lands in the handler and the loop simply continues. Then ask what else the handler catches: a bug that a deploy brings in fails for many records, and each one of them is skipped.
- Follow-ups
-
- How do you report how many records were skipped, and why?
- What should happen when most records fail?
- Where would you still catch
Exception?
From the lesson Handling exceptions with try and except
Model answer, Pro. Model answers open with any pass; prices are in the notice on this page.Opening the model answers with your pass…
Model answers open with any MySmartCoPilot pass.
- Pro pass · 1 week₹79$2.99
- 30 days₹179$5.99
- 1 year₹1,699$45
One payment; a pass never renews. The price shown is the total you pay: no fees or charges are added at checkout.
Passes can’t be bought right now, so the model answers can’t be opened at the moment. If you have a pass, enter your licence key.
It also opens every other in-depth part in Learn and every Pro tool. Sales are final, except where the law gives you a right to withdraw, for example in the EU and the UK (refund policy).
In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 3 minutes
-
Fresher to mid
A service calls
os.path.exists(path)and thenopen(path), yet its logs showFileNotFoundErrorfrom theopen()line a few times a day. How is that possible, how do you rewrite the code, and when is checking first still the better choice?- What it tests
- The time-of-check to time-of-use race, EAFP against LBYL, and catching only the file errors the code can handle.
- First step
- Point at the gap between the two calls: another process, a cleanup job or log rotation can remove the file after the check and before the open, so the check proves nothing. Then make the open itself the check: open the file in a try statement that handles FileNotFoundError.
- Follow-ups
-
- Which other
OSErrorsubclasses can the open raise, and should you catch them? - Is the race also a security problem?
- How would you test this race?
- Which other
From the lesson Handling exceptions with try and except
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 4 minutes
-
Mid to senior
InsufficientFundsError(balance, amount)passes only a formatted message tosuper().__init__(). Unit tests pass, but when the code runs in aProcessPoolExecutorworker, the caller getsBrokenProcessPoolinstead of the error, and every other task fails too. Why, and how do you fix and test the class?- What it tests
- How exceptions cross process boundaries by pickling, how pickle rebuilds an exception from its args, and reading the cause of a BrokenProcessPool.
- First step
- Read the BrokenProcessPool's __cause__: it is a traceback from the parent process that ends in a TypeError while unpickling. The worker sent the exception without trouble; rebuilding it calls the class with its args, and args holds only the message, while __init__ needs two values.
- Follow-ups
-
- Why did every other pending task of the pool fail as well?
- How would
__reduce__fix a class whose__init__you cannot change? - What test would have caught this before release?
From the lesson Raising exceptions and custom error classes
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 3 minutes
-
Fresher to mid
A payments service validates refunds with
assert amount > 0. Every test passes, yet production once accepted a refund of -2,000. What happened, how do you fix it, and where isassertstill the right tool?- What it tests
- Knowing that -O and PYTHONOPTIMIZE remove assert statements, validating with exceptions, and telling input checks from invariants.
- First step
- Ask how production starts Python. The -O option and the PYTHONOPTIMIZE environment variable remove every assert statement, and a start command, a container image or a service setting can switch them on, so the check simply did not exist there. Input checks need an if and a raise.
- Follow-ups
-
- How would you check whether production runs with
-O? - Which exception should the check raise, and what message?
- Should the check be in the API handler or in the refund function?
- How would you check whether production runs with
From the lesson Raising exceptions and custom error classes
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 3 minutes
-
Mid to senior
An API's error pages show the full traceback, including a file path and a database URL with its password. Redesign the error path: what the client sees, what the log keeps, and how support finds the log entry for one customer's complaint.
- What it tests
- Separating user messages from diagnostics, logging with the exception's traceback, correlating requests with IDs, and keeping secrets out of responses and logs.
- First step
- Treat it as two problems: a leak of internals and a missing way to diagnose. Catch unexpected exceptions once, at the request boundary; log them with logger.exception() and a request ID; return a fixed message that quotes the ID. Then rotate the password, which the pages have already published.
- Follow-ups
-
- How do you keep the password out of the log as well?
- Which errors may show their message to the client?
- What changes for a command-line tool?
From the lesson Exception chaining, notes and tracebacks
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 4 minutes
-
Mid to senior
A data import of 40 files with 100,000 rows each fails with only
ValueError: could not convert string to float: 'N/A'. How do you make the next failure name the file, the row and the column, without changing every function's signature or the exception type that callers catch?- What it tests
- Adding context with notes at the level that knows it, keeping the original type and traceback, and choosing between failing fast and collecting errors.
- First step
- Find the loop that knows the file and the row, and catch ValueError there, around the conversion of one value. Add a note with the file, row and column using add_note(), then re-raise with a bare raise, so the type, message and traceback stay exactly as they were.
- Follow-ups
-
- Should the import stop at the first bad row or collect them?
- Would
raise ImportFailedError(...) from errbe better? - What does a note cost per row?
From the lesson Exception chaining, notes and tracebacks
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 4 minutes
-
Mid to senior
A request handler fetches prices, stock and reviews in an
asyncio.TaskGroup. Itsexcept TimeoutError:never runs: when the reviews service times out, the request fails with anExceptionGroupand the prices are lost. Why, and how do you return partial results while unexpected errors still surface?- What it tests
- How a TaskGroup reports failures, except against except*, the cancellation of sibling tasks, and designing required and optional calls.
- First step
- A TaskGroup raises an ExceptionGroup, and a group is not a TimeoutError, so the clause never matches; the first failure also cancels the tasks still running. Decide which calls are optional, and let those catch their own expected errors inside the task, so they never reach the group.
- Follow-ups
-
- Would
asyncio.gather(..., return_exceptions=True)be simpler, and what do you lose? - What happens if one task raises
KeyboardInterrupt? - How do you put a time limit on the whole request?
- Would
From the lesson Exception groups and except*
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 3 minutes
-
Mid to senior
Design how a sign-up API reports every invalid field at once, including those of a nested address form, as a JSON list for the client, while a programming error such as a
TypeErrorstill produces a 500. Which exceptions do you define, and where do you catch what?- What it tests
- Designing exception groups for validation, nesting and flattening groups, separating expected errors from bugs with except*, and mapping errors to responses.
- First step
- Define one FieldError with field and problem attributes, derived from ValueError. Each validator collects its FieldErrors and raises one ExceptionGroup; a sub-form raises its own group, which the parent nests. At the request boundary, except* FieldError builds the 400 response, and anything else is raised again.
- Follow-ups
-
- Should validation raise a group or return a list of errors?
- How do you give nested fields names such as
address.pin? - How do you test the handler?
From the lesson Exception groups and except*
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 4 minutes
-
Mid to senior
A report function takes a lock file, opens a database connection and an output file, and releases all three by hand at its end. When the output folder is missing, the connection leaks and the lock file stays behind, so the next run refuses to start. How do you restructure it, and how do you prove nothing leaks?
- What it tests
- Using with and ExitStack for several resources, the order of release, failures during setup, and testing the clean-up on every path.
- First step
- List each resource and the line that releases it. Releases at the end of the function are skipped whenever an earlier line raises, so each resource needs its own with statement, or an ExitStack entry, from the moment it is acquired.
- Follow-ups
-
- The lock file must be removed even when closing the connection fails. In which order do you release?
- How do you test that the connection is closed when opening the output file fails?
- The number of output files depends on the data. What changes?
From the lesson Context managers and the with statement
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 4 minutes
-
Mid to senior
Design a context manager that makes changes to an in-memory store all-or-nothing, like a database transaction. What happens when the block raises
KeyboardInterrupt, when the store holds lists that the block changes in place, and when transactions are nested?- What it tests
- Designing __enter__ and __exit__ for rollback, shallow against deep snapshots, which exceptions roll back, and nesting with a stack of snapshots or undo logs.
- First step
- State the contract first: on a normal exit the changes stay; on any exception the store returns to its earlier state and the exception continues. A snapshot taken in __enter__ and restored in place in __exit__ meets it, as long as nothing the block changes is shared with the snapshot.
- Follow-ups
-
- The store holds lists, and the block appends to them. What breaks, and what does a deep copy cost?
- How do nested transactions behave, and what does an inner rollback undo?
- Should KeyboardInterrupt roll back too?
- The store has a million keys. Is a full copy per transaction acceptable?
From the lesson Context managers and the with statement
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 5 minutes
-
Mid to senior
Your team's internal library is used by 30 services. You must rename
get_rate()tofetch_rate()and remove the old name within two releases, without breaking any service. How do you deprecate it so that every caller notices in time, and how do you know it is safe to remove?- What it tests
- Issuing DeprecationWarning at the caller's line, why default filters hide it in services, failing CI on it, and measuring the remaining callers before removal.
- First step
- Keep get_rate() working as a thin wrapper around fetch_rate() that warns with DeprecationWarning at the caller's line, or mark it with warnings.deprecated on 3.13 and later. Then plan for visibility: the default filters hide this warning in every service, so it must reach their tests and editors.
- Follow-ups
-
- Why would the services' developers never see the warning in production logs?
- How do you make the warning fail CI without breaking production?
- How do you find out which services still call the old name?
From the lesson Warnings, assertions and development mode
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 4 minutes
-
Mid to senior
After you add
python -X devto CI, one run prints 2,400 warnings: ResourceWarnings about unclosed files and sockets, DeprecationWarnings from your code and from two libraries, and a few RuntimeWarnings about coroutines that were never awaited. How do you triage them, and how do you keep CI strict without drowning the team?- What it tests
- What each warning category means, finding a leak's source with tracemalloc, narrow filters per category and module, and making fixed classes of warnings fail the build.
- First step
- Group before fixing: count the warnings by category and by the file and line they name, because a few lines usually produce most of them. Then deal with the never-awaited coroutines first: each one is a call whose code silently never ran.
- Follow-ups
-
- A ResourceWarning names a line in the test framework, not your code. How do you find the real source?
- Which warnings would you make errors first, and how?
- One library's DeprecationWarning cannot be fixed until its next release. What do you do?
From the lesson Warnings, assertions and development mode
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 4 minutes
-
Mid to senior
You inherit a 4,000-line data pipeline in which 60 functions wrap their bodies in
try/except Exception, print the error and returnNone. Failures show up as wrong totals, and one failure is logged up to five times. How do you restructure the error handling, step by step, without a risky rewrite?- What it tests
- Where errors should be caught, converting errors at module boundaries, logging once, keeping deliberate recovery, and refactoring safely behind tests.
- First step
- Do not delete handlers first. Pin today's behaviour with tests, then classify each handler: a real recovery the pipeline needs, context that should travel with the error, or a handler that only hides an error. Decide the boundaries, each stage's edge and the job runner, and remove or rewrite every handler between them.
- Follow-ups
-
- Some handlers really do skip bad rows on purpose. How do you keep that behaviour?
- How do you stop one failure from being logged five times?
- What should the pipeline's exit status be when 3 of 10,000 rows were bad?
From the lesson Designing error handling for real programs
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 4 minutes
-
Mid to senior
A nightly job sends 5,000 payout requests to a payment provider's API. About 1 % time out, and a simple retry once paid three vendors twice. Design the retry policy: which failures you retry, how long you wait, how you avoid paying twice, and what happens to payouts that never succeed.
- What it tests
- Idempotency and idempotency keys, temporary against permanent failures, capped backoff with jitter, Retry-After, and reconciling outcomes that stay unknown.
- First step
- Separate two questions: is the failure temporary, and is it safe to send the request again? A timeout does not say whether the payout was made, so a retry is safe only if the provider can recognise a repeat, for example by an idempotency key that stays the same for every attempt of one payout.
- Follow-ups
-
- The provider has no idempotency keys. What do you do after a timeout?
- How many attempts, and how long can the whole job take?
- The provider answers 429 with Retry-After: 30. What changes?
- Where do the payouts that still failed end up?
From the lesson Designing error handling for real programs
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 4 minutes