Handling IO exceptions

Up to now, when Python has encountered an error, it stops the program and displays an error message. Python, however, is a bit clever than that. Using the try construction, you can ask Python to look for specific problems or errors when you run a particular part of a program. An error or problem in the flow of a program is called an 'exception' and the code that handles this is the 'exception handling routine'. If an exception does happen, we talk about an exception being 'raised' or 'thrown'.

Python has lots of very specific problems (or 'exceptions') it can look for. When you are writing to or reading from files, for example, you might have a situation where the storage device is full, where a file already exists that you are trying to create, where a USB pen drive has been pulled out halfway through a reading or writing process, where you are trying to read from a file that doesn't exist or one which has been moved to a different folder so Python cannot find it, and so on. When you get more experienced, you can write and use your own exceptions. The format for the try construction is as follows (although there are others):

    do these instructions. If there isn't an error, then do the else part and then leave the construction.
except XXXX
    if there is an error of type XXXX, do these instructions.
except YYYY
    if there is an error of type YYYY, do these instructions.
    do these instructions if Python was able to run the code without an exception.

This activity will make more sense if you have done some of the activities in the 'File operations' section.

Q1. Get this code working in Python: 

#Handling an error associated with writing to and reading from a file.
    writefile = open("testFile", 'w')
    writefile.write("This is a lot of data that I want to save to a file")
    print('You can put some more lines of code here.')
except IOError:
    print ("Error: can't write the data to the file for some reason.")
    print ("Content written to the file successfully.")

Q2. The above code uses a try construction that follows this pattern:

    do these instructions
except XXXX
    do these instructions if Python spots an IO error.
    do these instructions if Python was able to run the code without an exception

What is the name of the file that Python writes to. Where is it stored? Open it up in Notepad or a similar text editor and examine the contents.
Q3. Now get this code working (note that the filename is deliberately called 'toastFile'):

#Handling an IO error

    readfile = open("toastFile", 'r')
    print('File read successfully.')
except IOError:
    print ("Error: can't find file or read data.")
    print ("Read content from the file successfully.")

What happens when you run this code. Explain your answer.
Q4. What happens when you change the filename from toastFile to testFile and rerun the program? Explain your answer. 
Q5. What happens when you change the access mode from 'r' to 'w'? Explain your answer.