datarekha
Python Medium Asked at GoogleAsked at StripeAsked at Atlassian

What do the else and finally clauses of a try block do, and when does finally NOT run?

The short answer

The else clause runs only when the try block exits without raising an exception — it lets you separate success-path code from the guarded block. The finally clause runs in every case: after normal exit, after an exception (caught or uncaught), and after a return or break inside try or except. The only situations where finally is skipped are a hard interpreter crash (SIGKILL, os._exit, power loss).

How to think about it

What the question is really after

Most candidates know try/except. The follow-up on else and finally tests whether you understand the execution model precisely — especially the subtle ways finally interacts with return and break. Getting this right signals you write production-grade code, not just happy-path code.

Full anatomy of a try block

The four clauses have distinct roles:

try:
    result = risky_call()          # guarded code
except ValueError as e:
    handle_value_error(e)          # specific exception
except (TypeError, KeyError) as e:
    handle_other(e)                # multiple types
else:
    process(result)                # ONLY if try succeeded
finally:
    cleanup()                      # ALWAYS runs

The else clause is the subtle one. Without it you’d be tempted to put process(result) inside the try block — but then any exception process raises would be caught by the except handlers, which is almost never what you want. else separates “protected code” from “success-path code” cleanly.

Try it yourself

finally survives break and continue

for i in range(3):
    try:
        if i == 1:
            break
    finally:
        print(f"cleanup {i}")   # runs for i=0 and i=1 (the break)

When finally genuinely does not run

  • os._exit() — bypasses the Python interpreter shutdown entirely.
  • SIGKILL sent from outside the process — the OS terminates without unwinding the stack.
  • A C-level segfault in an extension — the interpreter crashes before Python’s exception machinery runs.
import os
try:
    os._exit(1)   # no finally, no atexit handlers
finally:
    print("never printed")

The key insight

Think of else as “then” and finally as “always”. The pattern try / except / else / finally maps directly to: “try this, handle errors, do this on success, always clean up.” Keeping those four concerns in separate clauses makes control flow transparent in code review.

Learn it properly Errors & Exceptions

Keep practising

All Python questions

Explore further

Skip to content