File Reading/Writing and Try/Except
Simple File Reading

Suppose you have a file called "fred.txt" which contains the following 3 lines:

To be, or not to be,
That's really not the question,
Nor the answer.

You want to read the file and end up with all of the text in a single string variable named "harry".  Assuming that your program and "fred.txt" are in the same directory, and you have permission to read the file... then

# open the file, creating a "file handle" and use that handle
# to read the data into a string variable

f = open('fred.txt','r')
harry = f.read()
# now, close the file handle
f.close()

... will do the trick.  Now, harry looks like this:

"To be, or not to be,\nThat's really not the question,\nNor the answer."

You can now split harry into a list of lines, and process the lines individually.  Or, instead, split it immediately into a list of words, and process those words...

lines = harry.split('\n')
words = harry.split()
Simple File Writing

Suppose our job was to write the contents of "fred.txt" into a new file called "george.txt", but with the lines in reverse order...  So...

# read lines in:
f = open('fred.txt','r')
harry = f.read()
f.close()

# separate into lines
lines = harry.split('\n')

# open the file "george.txt" for writing
ron = open('george.txt','w')

# write out the lines in reverse order
for aline in lines[::-1]:
   ron.write(aline+'\n') 
   # had to add the "\n" to each line because it was
   # swallowed by the .split('\n') above

# must close the file
ron.close()

What can possibly go wrong??

Lots. For instance:

  • Suppose there is no "fred.txt" file?
  • It's not in the current directory, but rather somewhere else in the file system?
  • The file is here and available but your program does not have the permission to read it?

So this is an operation that might fail, and if so, might crash your program.  While that's not terrible, if you're creating a program for yourself.  But it is terrible, if you're creating a program to be used by other people.

 Suppose that you've created a program, to be used by other people who interact with it and provide it with the name of a file to work on.  You don't want the program to crash if the user requests a file that can't be read for any of the reasonsn mentioned above.  In this situation, the program will print an obscure error message to the user who will not be able to interpret it, and stop.  You, as the programmer, want to have some control over this situation.

Enter the try/except keywords...

try/except

Suppose you want the program to recover if it can't read a file that the user has provided.  You want it to simply print an understandable instruction to the user and try again.  Here's an example:

while True:
  
# get the name of a file from the user...
   thefile = input('Name of file (or "quit" to exit): ')

   if thefile == 'quit':
      print('Program terminating...')
      break  # get out of the while loop

   try:
     
# try these 3 commands. If any fail, go to except
      f = open(thefile,'r')
      print(f.read())
      f.close()
     
# now skip the except block because this worked

   except:
      # we're here because some command failed in the
      #   try block (probably the open())

      print('Could not read:',thefile)

   file_attempts += 1
 
 # bottom of while loop, go back to top

print('Total file attempts: ',file_attempts)

Explanation:

"input()" is a function that takes a string as a prompt, and prints that prompt on the screen and waits for and captures the user's typed response, and returns that as a string.

"try:" starts a block of indented code with commands that might fail and Python will attempt to execute that code.  If all of the commands in that indented code block (before the "except:" statement) execute without a problem, then the "except:" code block is skipped, and then the program will continue after that.

If an error occurs anywhere in the "try:" code block, then Python immediately jumps to the "except:" block of code and executes the commands in that block.  And then Python goes on to the commands after the "except:" block of indented code.
More on exceptions

The "except:" block, in the example above, will catch all types of errors that occur in the "try:" block.  But you may want to tell the user of the program just what kind of error occured.  Was it because the file didn't exist, or because the program didn't have permission to read it, etc.?  Python will tell you if you want...

Instead of the simple "except:" statement, here's a more complicated one that captures the error message that Python would have printed on the screen, and now you can print it yourself, in a nicer form. And the program doesn't crash.

   try:
      blah, blah, blah...
   except Exception as voldy:
      print('There was a error: ', voldy)
      print('so, you might want to try again')
What if the file isn't "there"?

This is the same problem that we would have on the command-line, when looking for a file that might not be there.  We could navigate around the file system and use commands like "cd" and "pwd" and "ls" to look around. Then, once we've found the missing file (possibly we were in the wrong place looking for it), we'll then be able to open it.

One can do all this in Python after importing the "os" library:

import os

Unix command Python method
pwd os.getcwd()
cd directoryname os.chdir(directoryname)
ls os.listdir()
ls directoryname os.listdir(directoryname)


Imagine this small directory/file area:
/temp
    introcs  (a directory)
         sample.csv (a file)
         demo (a directory)
              fred.txt  (a file)
              george.txt  (a file)
   
  
import os
print(os.getcwd())
 
c:\temp\introcs   (if on Windows)
 
/temp/introcs    (if Mac or Unix)
print(os.listdir())
 
['demo', 'sample.csv']
print(os.listdir('demo'))
 
['fred.txt', 'george.txt']
os.chdir('demo')
print(os.getcwd())
 
c:\temp\introcs\demo  (if on Windows)
 
/temp/introcs/demo    (if on Mac or Unix)
Converting strings to numbers with Try/Except

This is a string:  "475.8"  It has 5 characters.
This is a number:  475.8.   You can add and multiply it.

Python has 2 functions "int()" and "float()" that will convert a string representation of a number into a number. Like so:

a = int('-47')
b = float('475.8')


However, if you give the function int() a string that cannot be converted into a integer, like "a4" or "fred" or even "4.5", then Python will crash with an error.  That's true of float() as well -- it will fail on "7.8qt", for instance. 

Can you tell ahead of time whether to give a string to one of these functions?

Yes, by using Try/Except. You can build functions that will tell you whether you can convert a string into an integer or a floating point number.

def IsAnInteger(somestring):
   try:
      a = int(somestring)
      return True
   except:
      return False

def IsAFloat(somestring):
   try:
      a = float(somestring)
      return True
   except:
      return False