Skip to content

Computer Science · Ch 1 — Exception Handling in Python

Recovering and continuing with finally clause

1.7.1

Recovering and continuing with finally clause

If an error is detected in the try block and the exception raised there is handled by a matching except clause, that except block runs as usual. But if the exception is not handled by any of the except clauses present, it is not simply dropped — the finally block (if present) still executes first, and only after finally has finished does Python re-raise the very same exception.

For example, Program 1.4 (seen earlier) contains only an except block for ZeroDivisionError. If any other type of error occurs, for which no handler (except clause) has been defined, the finally clause will still be executed first. Consider the code in Program 1-7 to understand this.

Program 1-7: Recovering through finally clause

print (" Practicing for try block")
try:
    numerator=50
    denom=int(input("Enter the denominator"))
    quotient=(numerator/denom)
    print ("Division performed successfully")
except ZeroDivisionError:
    print ("Denominator as ZERO is not allowed")
else:
    print ("The result of division operation is ", quotient)
finally:
    print ("OVER AND OUT")

Notice that, unlike Program 1-6, this program defines only an except ZeroDivisionError clause — there is no except ValueError handler this time.

While executing this code, if a non-numeric value (such as "var") is entered as input, int() raises a ValueError. Since no except clause here is written to catch a ValueError, the finally block still runs first, so the message "OVER AND OUT" is displayed. Only after finally completes is the unhandled ValueError re-raised, terminating the program with a traceback, as shown in the figure below.

Figure 1.13 shows exactly this: the shell prints "Practicing for try block", prompts for the denominator, and once a non-numeric value like var is entered, it prints "OVER AND OUT" and then the traceback ending in ValueError: invalid literal for int() with base 10: 'var'.

After the finally block finishes executing, Python transfers control to a previously entered outer try (if the current try is nested inside one) or to the next higher-level default exception handler. In other words, unlike an except clause, executing finally does not stop or catch the exception — the exception continues to be raised after finally has run. …

Figure 1.13Output of Program 1-7
Fig. 1.13 — Output of Program 1-7

Drawn by us to help you understand the concept clearly, and verified to make sure it's accurate. For exams, practice from your textbook's own diagram.

This is the output of Program 1-7, which demonstrates the finally clause, run with non-numeric input. After RESTART:, the program prints Practicing for try block and prompts Enter the denominator, to which the user types the text var instead of a number. The line denom=int(input("Enter the denominator")) then tries to convert 'var' to an integer with int(), which fails and raises ValueError: invalid literal for int() with base 10: 'var'.

This script's except clauses only handle ZeroDivisionError and ValueError-shaped cases through specific branches from earlier examples in the chapter — but the key thing shown here is the finally block: before the ValueError is allowed to propagate out and print its traceback, the finally clause runs first, printing OVER AND OUT. Only after that does the traceback appear, ending in the ValueError. …