try ... except ... else ... finally

The following code gives an example of the use of a try ... except ... else ... finally clause:

def process_file(filename):
    try:
        fi = open(filename, 'r')
    except IOError:
        print('Oops: couldn\'t open {} for reading'.format(filename))
        return
    else:
        lines = fi.readlines()
        print('{} has {} lines.'.format(filename, len(lines)))
        fi.close()
    finally:
        print('   Done with file {}'.format(filename))

    print('The first line of {} is:\n{}'.format(filename, lines[0]))
    # further processing of the lines ... 
    return

process_file('sonnet0.txt')
process_file('sonnet18.txt')

Within the else block, the contents of the file are only read if the file was successfully opened.

Within the finally block, Done with filename is printed whether the file was successfully opened or not.

Assuming that the file sonnet0.txt does not exist but that sonnet18.txt does, running this program prints:

Oops: couldn't open sonnet0.txt for reading
   Done with file sonnet0.txt
sonnet18.txt has 14 lines.
   Done with file sonnet18.txt
The first line of sonnet18.txt is:
Shall I compare thee to a summer's day?