Finally Return Swallows an Exception

Both functions raise inside try, but only one of them lets that exception escape:

def attempt_a():
    try:
        raise ValueError("boom")
    finally:
        return "recovered"

def attempt_b():
    try:
        raise ValueError("boom")
    finally:
        print("cleanup ran")

print(attempt_a())
print(attempt_b())

What happens when this runs?

A

attempt_a() returns "recovered", but the ValueError is only delayed: it still propagates immediately after attempt_a() returns, so print(attempt_a()) never actually prints "recovered".

B

attempt_a() returns "recovered" and the ValueError never propagates; attempt_b() prints cleanup ran, then the ValueError propagates out of attempt_b uncaught and crashes the program before its print(...) completes.

C

Both functions let the ValueError propagate: finally can run cleanup code, but it has no power over whether an exception keeps going, so the program crashes on attempt_a() first.

D

attempt_a() raises a RuntimeError complaining that an exception was still active during a return, since Python doesn't allow returning while unwinding an exception.