finally
ClauseOperating systems typically can prevent more than one program from manipulating a file at once. When a program finishes processing a file, the program should close it to release the resource. This enables other programs to use the file (if they’re allowed to access it). Closing the file helps prevent a resource leak in which the file resource is not available to other programs because a program using the file never closes it.
finally
Clause of the try
StatementA try
statement may have a finally
clause as its last clause after any except
clauses or else
clause. The finally
clause is guaranteed to execute, regardless of whether its try
suite executes successfully or an exception occurs.8 In other languages that have finally
, this makes the finally
suite an ideal location to place resource-deallocation code for resources acquired in the corresponding try
suite. In Python, we prefer the with
statement for this purpose and place other kinds of “clean up” code in the finally
suite.
The following IPython session demonstrates that the finally
clause always executes, regardless of whether an exception occurs in the corresponding try
suite. First, let’s consider a try
statement in which no exceptions occur in the try
suite:
In [1]: try:
...: print('try suite with no exceptions raised')
...: except:
...: print('this will not execute')
...: else:
...: print('else executes because no exceptions in the try suite')
...: finally:
...: print('finally always executes')
...:
try suite with no exceptions raised
else executes because no exceptions in the try suite
finally always executes
In [2]:
The preceding try
suite displays a message but does not raise any exceptions. When program control successfully reaches the end of the try
suite, the except
clause is skipped, the else
clause executes and the finally
clause displays a message showing that it always executes. When the finally
clause terminates, program control continues with the next statement after the try
statement. In an IPython session, the next In
[]
prompt appears.
Now let’s consider a try
statement in which an exception occurs in the try
suite:
In [2]: try:
...: print('try suite that raises an exception')
...: int('hello')
...: print('this will not execute')
...: except ValueError:
...: print('a ValueError occurred')
...: else:
...: print('else will not execute because an exception occurred')
...: finally:
...: print('finally always executes')
...:
try suite that raises an exception
a ValueError occurred
finally always executes
In [3]:
This try
suite begins by displaying a message. The second statement attempts to convert the string 'hello'
to an integer, which causes the int
function to raise a ValueError
. The try
suite immediately terminates, skipping its last print
statement. The except
clause catches the ValueError
exception and displays a message. The else
clause does not execute because an exception occurred. Then, the finally
clause displays a message showing that it always executes. When the finally
clause terminates, program control continues with the next statement after the try statement. In an IPython session, the next In
[]
prompt appears.
with
Statements and try
…except
Statements Most resources that require explicit release, such as files, network connections and database connections, have potential exceptions associated with processing those resources. For example, a program that processes a file might raise IOError
s. For this reason, robust file-processing code normally appears in a try
suite containing a with
statement to guarantee that the resource gets released. The code is in a try
suite, so you can catch in except
handlers any exceptions that occur and you do not need a finally
clause because the with
statement handles resource deallocation.
To demonstrate this, first let’s assume you’re asking the user to supply the name of a file and they provide that name incorrectly, such as gradez.txt
rather than the file we created earlier grades.txt
. In this case, the open
call raises a FileNotFoundError
by attempting to open a non-existent file:
In [3]: open('gradez.txt')
-------------------------------------------------------------------------
FileNotFoundError Traceback (most recent call last)
<ipython-input-3-b7f41b2d5969> in <module>()
----> 1 open('gradez.txt')
FileNotFoundError: [Errno 2] No such file or directory: 'gradez.txt'
To catch exceptions like FileNotFoundError
that occur when you try to open a file for reading, wrap the with
statement in a try
suite, as in:
In [4]: try:
...: with open('gradez.txt', 'r') as accounts:
...: print(f'{"ID":<3}{"Name":<7}{"Grade"}')
...: for record in accounts:
...: student_id, name, grade = record.split()
...: print(f'{student_id:<3}{name:<7}{grade}')
...: except FileNotFoundError:
...: print('The file name you specified does not exist')
...:
The file name you specified does not exist
(True/False) If a finally
clause appears in a function, that finally
clause is guaranteed to execute when the function executes, regardless of whether the function raises an exception.
Answer: False. The finally
clause will execute only if program control enters the corresponding try
suite.
(Fill-In) Closing a file helps prevent a(n) in which the file resource is not available to other programs because a program using the file never closes it.
Answer: resource leak.
(IPython Session) Before executing the IPython session, determine what the following function displays if you call it with the value 10.7
, then the value 'Python'
?
def try_it(value)
try:
x = int(value)
except ValueError:
print(f'{value} could not be converted to an integer')
else:
print(f'int({value}) is {int(value)}')
finally:
print('finally executed')
Answer:
In [1]: def try_it(value):
...: try:
...: x = int(value)
...: except ValueError:
...: print(f'{value} could not be converted to an integer')
...: else:
...: print(f'int({value}) is {int(value)}')
...: finally:
...: print('finally executed')
...:
In [2]: try_it(10.7)
int(10.7) is 10
finally executed
In [3]: try_it('Python')
Python could not be converted to an integer
finally executed
3.133.147.87