Python Interview Questions: Errors and Control Flow

Reviewed by Mark Dickie · Last updated

1 question on this page you can answer and see marked on the spot. Go to the first one

Python error handling is the set of statements that let a program raise, catch, and recover from exceptions while deciding which code runs next. Interviewers mostly probe the execution order of try, except, else, and finally, plus what happens when a second exception is raised inside a handler. Expect questions on the exception hierarchy, raise from, and context managers, since those are where candidates most often lose points.

Which Python error-handling details do interviewers check?

MechanismWhat the interviewer checks
try / except / else / finallyWhether you know else runs only when no exception occurred, and finally runs even after a return
return inside finallyWhether you see that it silently overrides a return value or a pending exception
raise ... from errWhether you can set cause to keep the original traceback when wrapping an error
Bare raiseWhether you know it re-raises the exception currently being handled
except Exception vs bare exceptWhether you can explain that bare except also catches KeyboardInterrupt and SystemExit
exit returning TrueWhether you know it suppresses the exception inside a with-block
for / while elseWhether you know the else clause runs only when the loop ends without break
StopIteration inside a generatorWhether you know PEP 479 turns it into a RuntimeError

Work through these hands-on exercises before the quiz:

  1. Write a retry function that calls an operation three times, then re-raises the last failure with raise ... from.
  2. Predict the output of a function whose try block returns and whose finally block also returns.
  3. Build a class-based context manager whose exit suppresses only ValueError and lets everything else propagate.
  4. Explain why a bare except in a long-running loop can make Ctrl+C appear to do nothing.

Key facts

  • Tarmac has 17 Python interview questions on this topic, 10 of them on this page, at difficulty 1–4 of 5.
  • Tarmac tracked 8,123 job postings asking for Python in October 2026.
  • Roles asking for Python advertise a median base salary of £75,000, across 2,295 job postings as of October 2026.
  • Tarmac last reviewed these Python interview questions on 2 November 2026.

At a glance

Questions10 shown · 17 in the bank
Difficulty1–4 of 5
FormatsOrdering, Code output, Coding exercise, Short answer
Interactive2 run your code against tests, in the app

What you'll review

  1. try except else finally
  2. exceptions
  3. pattern matching
  4. eafp lbyl

Practice questions

Try one before you open the answer. Pick an option and press Check; it's marked on the spot.

For a try block that completes WITHOUT raising, order the clauses by when their bodies run.#

Put these in order

Show answer

On the no-exception path the clauses run in this order:

  1. try: body
  2. else: body (runs only if no exception)
  3. finally: body

The try body runs to completion, then else runs because the block succeeded, then finally always runs last. The except clause is skipped because nothing was raised.

Why:

On the no-exception path the try body runs to completion, then else (its whole point — code that should run only when try succeeded), then finally always runs last. except is skipped because nothing was raised.

What does the following Python code print when executed?#

try:
    x = 10 // 0
    print('A')
except ZeroDivisionError:
    print('B')
finally:
    print('C')
print('D')
Show answer
B
C
D
Why:

Tracing step by step: x = 10 // 0 raises a ZeroDivisionError, so print('A') is skipped. The except ZeroDivisionError block catches the error and prints B. The finally block always executes regardless of whether an exception was raised, printing C. After the entire try/except/finally construct completes, execution continues normally and print('D') prints D. The output, one line per print, is therefore B, C, D.

What is printed when the following Python 3.10+ code runs?#

x = [1, 2]
match x:
    case [a, b]:
        print(a + b)
    case [a, b, c]:
        print(a + b + c)
    case _:
        print("no match")
Show answer
3
Why:

x is [1, 2], a two-element list. The first case [a, b] pattern matches a two-element sequence, binding a = 1 and b = 2. The matched block executes print(a + b), which prints 3. The remaining patterns ([a, b, c] and _) are never reached because pattern matching stops at the first successful match.

Implement safe_lookup_ratio(data, key, divisor): return data[key] / divisor. Using the EAFP style (try/except, not pre-checks), return the string "undefined" if key is missing OR divisor is 0. Assume present values are numeric, and the valid test cases all produce a non-integer ratio.#

Starter code

def safe_lookup_ratio(data, key, divisor):
    # TODO: EAFP — try the operation, handle the failure
    return data[key] / divisor

Your solution must pass

  • normal division
  • missing key

This one is written and run, not read. Solve it in the app and your code is executed against these tests and the hidden ones.

What does the following Python code print?#

def foo():
    try:
        return 1
    except Exception:
        return 2
    else:
        return 3
    finally:
        return 4

print(foo())
Show answer
4
Why:

The try block evaluates return 1 with no exception raised. Because a return statement was executed inside the try block, the else clause is skipped (Python only runs else when the try block completes without a return, break, continue, or exception). The finally block always executes regardless of how the try/except/else clauses were left. Since finally contains its own return 4, it overrides the pending return 1 from the try block, so foo() returns 4 and the program prints 4.

What does this print, one value per line?#

def describe(point):
    match point:
        case (0, 0):
            return "origin"
        case (x, 0):
            return f"on x-axis at {x}"
        case (0, y):
            return f"on y-axis at {y}"
        case _:
            return "somewhere else"

print(describe((0, 0)))
print(describe((5, 0)))
print(describe((3, 4)))
Show answer
origin
on x-axis at 5
somewhere else
Why:

match tries cases top to bottom and uses the first structural match. (0, 0) hits the literal origin case. (5, 0) fails the first case but matches (x, 0), binding x = 5. (3, 4) matches none of the specific patterns, so the wildcard case _ returns "somewhere else".

Explain EAFP versus LBYL in Python, and why EAFP is often preferred.#

Show answer

LBYL (look before you leap) checks preconditions first — e.g. if key in d: before d[key]. EAFP (easier to ask forgiveness than permission) just attempts the operation and catches the exception with try/except. EAFP is often idiomatic because it avoids a redundant lookup and sidesteps race conditions between the check and the use, since the check-then-act window can go stale.

Why:

EAFP attempts the action and handles the resulting exception; LBYL guards with an up-front test. EAFP avoids the time-of-check/time-of-use race and the double lookup, and is the Pythonic default for dict access, file I/O, and attribute access.

What does the following Python code print? Consider how else, finally, and a return inside except interact, especially when the returned object is a mutable list.#

def f():
    result = []
    try:
        result.append(1)
        raise ValueError()
    except ValueError:
        result.append(2)
        return result
    else:
        result.append(3)
    finally:
        result.append(4)

print(f())
Show answer
[1, 2, 4]
Why:

The try block appends 1 then raises ValueError. The except ValueError block catches it, appends 2, and issues return result — but Python guarantees finally runs before the return actually completes. The else block is skipped entirely because an exception was raised (it only runs when no exception occurs in try). The finally block appends 4 to the same list object that return is about to yield. Because lists are mutable, the caller sees the post-finally state [1, 2, 4].

What does this print, one value per line?#

def f():
    try:
        print("try")
        return "result"
    except Exception:
        print("except")
    else:
        print("else")
    finally:
        print("finally")

print(f())
Show answer
try
finally
result
Why:

The try block prints try and hits return. The else clause runs only when the try block completes without returning or raising, so the return skips it entirely. finally always runs before the function actually exits, printing finally, and then the pending return value "result" is delivered.

Implement retry(func, max_attempts, base_delay, sleep): call func(); if it raises, sleep then retry, up to max_attempts total attempts. Use exponential backoff: the delay before retry attempt k (1-indexed, the first retry) is base_delay * 2**(k-1) — so base_delay, 2*base_delay, 4*base_delay, …. Record each delay by calling the injected sleep(delay) (never sleep for real). Return {"outcome": <value>, "attempts": <int>, "delays": [...]} on success; if all attempts fail, set outcome to the string "failed". The run_retry driver below the # ---- test driver (do not edit) ---- line builds a function failing the first fail_times calls and an injected sleep recorder.#

Starter code

def retry(func, max_attempts, base_delay, sleep):
    # TODO: call func, back off and retry on failure, record delays
    return {"outcome": func(), "attempts": 1, "delays": []}

# ---- test driver (do not edit) ----
def run_retry(fail_times, max_attempts, base_delay):
    delays = []
    state = {"calls": 0}
    def flaky():
        state["calls"] += 1
        if state["calls"] <= fail_times:
            raise ValueError("boom " + str(state["calls"]))
        return "ok"
    def sleep(delay):
        delays.append(delay)
    return retry(flaky, max_attempts, base_delay, sleep)

Your solution must pass

  • succeeds on third attempt
  • succeeds first try, no sleeps

This one is written and run, not read. Solve it in the app and your code is executed against these tests and the hidden ones.

Sources

The official documentation these questions are checked against:

Related interview questions

Job market

See python salaries and hiring demand from live job postings.

The other 7 questions

This page shows 10 and marks what you pick. That's as far as a page can go. A free account opens the other 7 and keeps every answer. What you miss comes back until it's right: after a day, then at longer gaps.

Start with this topic

Free · the whole bank · 100 marked answers per 30 days · written feedback on the paid plan

Interview booked? Practise the job ad instead

What moved, monthly

One email a month when the bulletin comes out: what moved in the markets we track, and the new question topics we published. Confirm your address to join. Unsubscribe any time.