Learning Resources
 

Try Finally and the with statement


Try .. Finally

Suppose you are reading a file in your program. How do you ensure that the file object is closed properly whether or not an exception was raised? This can be done using the finally block. Note that you can use an except clause along with a finally block for the same corresponding try block. You will have to embed one within another if you want to use both.

#!/usr/bin/python
# Filename: finally.py
 
import time
 
try:
    f = open('poem.txt')
    while True: # our usual file-reading idiom
        line = f.readline()
        if len(line) == 0:
            break
        print(line, end='')
        time.sleep(2) # To make sure it runs for a while
except KeyboardInterrupt:
    print('!! You cancelled the reading from the file.')
finally:
    f.close()
    print('(Cleaning up: Closed the file)')

Output:

   $ python finally.py
   Programming is fun
   When the work is done
   if you wanna make your work also fun:
   !! You cancelled the reading from the file.
   (Cleaning up: Closed the file)

How It Works:

We do the usual file-reading stuff, but we have arbitrarily introduced sleeping for 2 seconds after printing each line using the time.sleep function so that the program runs slowly (Python is very fast by nature). When the program is still running, press ctrl-c to interrupt/cancel the program.

Observe that the KeyboardInterrupt exception is thrown and the program quits. However, before the program exits, the finally clause is executed and the file object is always closed.

The with statement

Acquiring a resource in the try block and subsequently releasing the resource in the finally block is a common pattern. Hence, there is also a with statement that enables this to be done in a clean manner:

#!/usr/bin/python
# Filename: using_with.py
 
with open("poem.txt") as f:
    for line in f:
        print(line, end='')

How It Works:

The output should be same as the previous example. The difference here is that we are using the open function with the with statement - we leave the closing of the file to be done automatically by with open.

What happens behind the scenes is that there is a protocol used by the with statement. It fetches the object returned by the open statement, let's call it "thefile" in this case.

It always calls the thefile.__enter__ function before starting the block of code under it and always calls thefile.__exit__ after finishing the block of code.

So the code that we would have written in a finally block should be taken care of automatically by the __exit__ method. This is what helps us to avoid having to use explicit try..finally statements repeatedly.

-Swaroopch