Propagation Past a Mismatched Except

A custom exception subclasses Exception, and one caller only guards against KeyError:

class InsufficientFundsError(Exception):
    pass

def charge(amount):
    if amount > 100:
        raise InsufficientFundsError(f"cannot charge {amount}")
    print(f"charged {amount}")

def process_order(amount):
    try:
        charge(amount)
    except KeyError:
        print("handled a KeyError")
    finally:
        print("cleanup")

process_order(50)
process_order(500)
print("done")

What is printed, and does print("done") ever run?

A

charged 50, cleanup, cleanup, done: the exception is discarded once it exits process_order because nothing declared except InsufficientFundsError anywhere.

B

charged 50, cleanup, cleanup, then an uncaught InsufficientFundsError crashes the program before print("done") runs.

C

charged 50, cleanup, handled a KeyError, cleanup, done: except KeyError still catches InsufficientFundsError since both are built on Exception.

D

charged 50, cleanup, then the program crashes immediately with InsufficientFundsError: the second cleanup never prints because finally doesn't run when the except clause doesn't match the raised exception type.