Program Flow Control with Conditionals
A program that opens a file makes an assumption: the filename supplied by the user refers to a file that exists and can be read.
When File Opening Fails
A program that opens a file makes an assumption: the filename supplied by the user refers to a file that exists and can be read. That assumption may be wrong. A user might enter a filename that does not exist or type text such as "na na boo boo" instead of a real filename. Without protection, the program crashes and the user sees a confusing traceback. The try/except structure lets the program anticipate this failure and respond with a helpful message.
The try block contains code that might fail. The except block contains recovery code that runs only when something goes wrong in the try block.
The Two Control-Flow Paths
Python chooses one of two paths. If the try block succeeds, Python skips the except block entirely and execution continues after the try/except structure. If the try block fails, Python immediately jumps to the except block. The statements after the structure run only if the program continues past it; they do not run if the except block calls exit().
A Protected File Operation
filename = input("Enter a filename: ")
try:
fhand = open(filename)
except:
print("Unable to open the file. Please check the filename.")
exit()
count = 0
for line in fhand:
if line.startswith("Subject:"):
count = count + 1
print("Subject lines:", count)- 1The input statement obtains a filename from the user.
- 2The try block contains the risky open operation.
- 3If open succeeds, fhand is assigned and Python skips the except block.
- 4If open fails, Python jumps to the except block.
- 5The except block prints a helpful message and calls
exit(). - 6When the file is available, the later statements count lines that start with "Subject:" and print the count.
This example follows the file-opening scenario described in the source. The rest of the program depends on fhand being a valid file object. If opening the file fails, continuing would not make sense, so the recovery code reports the problem and terminates the program instead of allowing a later operation to fail.
Tracing Success and Failure
Two runs of the file-opening program
Trace what happens when the user enters a valid filename and when the user enters an invalid filename.
- 1Valid filename
With a filename such as "
mbox.txt", the open call succeeds. fhand is assigned, the except block is skipped, and the program counts and prints the subject lines. - 2Invalid filename
With a filename such as "na na boo boo", the open call fails. Python immediately jumps to the except block, which prints the helpful error message and calls
exit(). - 3Statements after the structure
The counting loop and print statement run on the successful path. They never run after the invalid filename because
exit()terminates the program immediately.
The valid run continues to the file-processing code. The invalid run reports the problem and exits without showing a traceback.
Recovery or Termination
Entering the except block is not the same as ending the program. The except block is recovery code: it can print a message and, when appropriate, allow a program to continue. Calling exit() is a separate decision. It terminates the program immediately. In the file example, termination is appropriate because the later processing depends on fhand being a valid file object.
Mistakes with try/except
Common mistake Putting the risky file operation outside the try block.
What it looks likefhand = open(filename) try: print("File opened")Why it failsThe operation that may fail is not protected by try, so the except block cannot handle its failure.
Do this insteadPlace the open operation inside the try block.
Common mistake Assuming the except block runs after every try block.
What it looks likeThe file opens successfully, but the program still expects the except block to run.
Why it failsWhen the try block succeeds, Python skips the except block entirely.
Do this insteadPut success-path statements after the try/except structure.
Common mistake Calling exit() without explaining the failure.
What it looks likeexcept: exit()Why it failsThe program ends, but the user is not told what went wrong.
Do this insteadPrint a helpful error message in the except block before calling exit().
Common mistake Continuing to use the file after opening failed.
What it looks likeexcept: print("Could not open file") print(fhand)Why it failsThe rest of the program depends on fhand being a valid file object.
Do this insteadCall exit() when the failed file operation makes it impossible to proceed.
Practice the Paths
What do you think happens?
Suppose the user enters an invalid filename. Which part of the program runs next?
Reveal answer
The except block
When the open operation in the try block fails, Python immediately jumps to the except block. If that block calls exit(), the later loop and print statement do not run.
Trace both paths in the file-opening example. For a valid filename, identify which statements run after the try/except structure. For an invalid filename, identify the message that should be shown and explain why the counting loop does not run.
Hints
- A successful try block skips except.
- A failed try block transfers control immediately to except.
exit()stops the program immediately.
Graceful Failure
- 1Use try around a risky operation such as opening a file.
- 2If the try block succeeds, Python skips except and continues after the structure.
- 3If the try block fails, Python immediately jumps to except.
- 4Use the except block to provide a helpful error message and decide whether the program can continue.
- 5Use
exit()when the failure makes it impossible to proceed safely; it terminates the program immediately.
Key Takeaways
- try/except gives a program separate success and failure paths for risky operations.
- A successful try block skips except, while a failed try block immediately enters except.
- The except block should explain the problem clearly to the user.
exit()terminates the program and is appropriate when later code cannot safely continue.- Handling predictable file failures this way prevents confusing tracebacks and makes programs more user-friendly.