Handling a File Error
The else Block
To prevent what we just saw in the previous section, we can add one more block to the sequence: finally
. This block is always going to be executed, regardless of whether an exception was raised or not. For example:
filename = 'my_data.dat'
try:
file = open(filename)
data = file.read()
important_data = data[0]
except Exception as e:
if isinstance(e, IndexError):
print(e)
data = 'Information'
important_data = data[0]
else:
print('Unhandled exception')
finally:
important_data = 'A'
print(important_data)
This is, in the end, a very silly example, because we are setting important_data
to a special value, but I hope you can see the use of finally
. If there is something that you must absolutely be sure that is executed, you can include it in a finally statement.
finally
is very useful to be sure that you are closing a connection, the communication with a device, closing a file, etc. Generally speaking, releasing the resources.
Finally has a very interesting behavior, because it is not executed always at the same moment. Let's see the following code:
filename = 'my_data.dat'
try:
print('In the try block')
file = open(filename)
data = file.read()
important_data = data[0]
except FileNotFoundError:
print('File not found, creating one')
file = open(filename, 'w')
finally:
print('Finally, closing the file')
file.close()
important_data = 'A'
print(important_data)
First, run the code when the file my_data.dat doesn't exist. You should see the following output:
In the try block
File not found, creating one
Finally, closing the file
A
So, you see you went from the try
to the except
to the finally
. If you run the code again, the file will exist, and therefore the output will be completely different:
In the try block
Finally, closing the file
Traceback (most recent call last):
File "JJ_exceptions.py", line 7, in
important_data = data[0]
IndexError: string index out of range
What you can see here is that when an unhandled exception is raised, the first block to be executed is the finally
. You close the file immediately. And then, the error is re-raised. This is very handy because it prevents any kind of conflict with downstream code. You open, you close the file and then the rest of the program has to deal with the problem of the
IndexError
. If you want to try a program without exceptions, just write something into my_data.dat
and you will see the output.