Why do we need the "finally" clause in Python?

Solution 1:

It makes a difference if you return early:

try:
    run_code1()
except TypeError:
    run_code2()
    return None   # The finally block is run before the method returns
finally:
    other_code()

Compare to this:

try:
    run_code1()
except TypeError:
    run_code2()
    return None   

other_code()  # This doesn't get run if there's an exception.

Other situations that can cause differences:

  • If an exception is thrown inside the except block.
  • If an exception is thrown in run_code1() but it's not a TypeError.
  • Other control flow statements such as continue and break statements.

Solution 2:

You can use finally to make sure files or resources are closed or released regardless of whether an exception occurs, even if you don't catch the exception. (Or if you don't catch that specific exception.)

myfile = open("test.txt", "w")

try:
    myfile.write("the Answer is: ")
    myfile.write(42)   # raises TypeError, which will be propagated to caller
finally:
    myfile.close()     # will be executed before TypeError is propagated

In this example you'd be better off using the with statement, but this kind of structure can be used for other kinds of resources.

A few years later, I wrote a blog post about an abuse of finally that readers may find amusing.

Solution 3:

They are not equivalent. finally code is run no matter what else happens*. It is useful for cleanup code that has to run.


*: As Mark Byers commented, anything causes the process to terminate immediately also prevents the finally-code to run. The latter could be an os._exit(). or powercut, but an infinite loop or other things also fall into that category.

Solution 4:

To add to the other answers above, the finally clause executes no matter what whereas the else clause executes only if an exception was not raised.

For example, writing to a file with no exceptions will output the following:

file = open('test.txt', 'w')

try:
    file.write("Testing.")
    print("Writing to file.")
except IOError:
    print("Could not write to file.")
else:
    print("Write successful.")
finally:
    file.close()
    print("File closed.")

OUTPUT:

Writing to file.
Write successful.
File closed.

If there is an exception, the code will output the following, (note that a deliberate error is caused by keeping the file read-only.

file = open('test.txt', 'r')

try:
    file.write("Testing.")
    print("Writing to file.")
except IOError:
    print("Could not write to file.")
else:
    print("Write successful.")
finally:
    file.close()
    print("File closed.")

OUTPUT:

Could not write to file.
File closed.

We can see that the finally clause executes regardless of an exception. Hope this helps.