I am not sure why we need
try...except...finally statements. In my opinion, this code block
try: run_code1() except TypeError: run_code2() other_code()
is the same with this one using
try: run_code1() except TypeError: run_code2() finally: other_code()
Am I missing something?
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
- Other control flow statements such as
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.
They are not equivalent. Finally code is run no matter what else happens. It is useful for cleanup code that has to run.
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.")
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.")
Could not write to file. File closed.
We can see that the
finally clause executes regardless of an exception. Hope this helps.
The code blocks are not equivalent. The
finally clause will also be run if
run_code1() throws an exception other than
TypeError, or if
run_code2() throws an exception, while
other_code() in the first version wouldn’t be run in these cases.
As explained in the documentation, the
finally clause is intended to define clean-up actions that must be executed under all circumstances.
finallyis present, it specifies a ‘cleanup’ handler. The
clause is executed, including any
elseclauses. If an
exception occurs in any of the clauses and is not handled, the
exception is temporarily saved. The
finallyclause is executed. If
there is a saved exception it is re-raised at the end of the
def divide(x, y): try: result = x / y except ZeroDivisionError: print("division by zero!") else: print("result is", result) finally: print("executing finally clause") ... divide(2, 1) result is 2.0 executing finally clause divide(2, 0) division by zero! executing finally clause divide("2", "1") executing finally clause Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 3, in divide TypeError: unsupported operand type(s) for /: 'str' and 'str'
As you can see, the
finally clause is executed in any event. The
TypeError raised by dividing two strings is not handled by the
except clause and therefore re-raised after the
finally clause has been executed.
In real world applications, the finally clause is useful for releasing external resources (such as files or network connections), regardless of whether the use of the resource was successful.
In your first example, what happens if
run_code1() raises an exception that is not
other_code() will not be executed.
Compare that with the
other_code() is guaranteed to be executed regardless of any exception being raised.
finally is for defining “clean up actions”. The
finally clause is executed in any event before leaving the
try statement, whether an exception (even if you do not handle it) has occurred or not.
I second @Byers’s example.