File Input and Output Basics
Try/except structures prevent program crashes by catching exceptions and executing recovery code when operations fail.
The Hidden Assumption
A program that opens a file makes an assumption: the file exists and can be read. That assumption may be wrong. A user might enter a filename that does not exist, or the file might be locked by another program. If the failure is not handled, Python displays a traceback and the user may be left confused. A try/except structure lets the program anticipate the failure, provide useful feedback, and finish cleanly.
Opening a file is a common point of failure, so the open() operation belongs inside the try block when the program needs to handle an opening failure gracefully.
Two Paths Through the Program
The important question is what happens immediately after the program attempts to open the file. If the filename is valid and the file exists, open() succeeds, the file object is assigned to fhand, and execution continues after the try/except structure. If the filename does not exist, open() raises a FileNotFoundError. Python stops executing the try block and moves directly to the except block.
What do you think happens?
If open() raises a FileNotFoundError inside the try block, what happens to the statements later in that try block?
Reveal answer
Answer: Python stops the try block and moves to except.
When the file-opening operation raises the exception, Python immediately stops executing the try block. The except block handles the failure instead.
Control Moves to Except
The try block contains the operation that may fail. The except block contains the recovery code. When no exception occurs, the try block completes, the except block is skipped, and the program continues. When opening the requested file fails, Python transfers control from the try block to the except block. This transfer prevents the failed operation from producing an uncontrolled program crash.
A Complete Recovery Example
Consider a program that asks for a filename, opens the file, and then counts lines that start with the word Subject. The key design decision is that the opening attempt is protected by try/except. If the file is available, the program reaches the loop and prints the result. If it is unavailable, the except block identifies the file in a clear message and exits before the loop runs.
filename = input("Enter a filename: ") try: fhand = open(filename) except FileNotFoundError: print("File cannot be opened: " + filename) exit() count = 0 for line in fhand: if line.startswith("Subject"): count = count + 1 print(count)
File cannot be opened: missing.txtIn the failure case, the for loop and the final print statement after the try/except structure never execute. The recovery code has already explained the problem and ended the program cleanly.
Useful Feedback Instead of Tracebacks
| Raw system error | User-friendly recovery message |
|---|---|
| A Python traceback containing technical details | A clear statement that the file cannot be opened |
| May confuse the person using the program | Identifies the filename involved |
| Appears when the failure is not handled | Is deliberately printed by the except block |
A raw traceback describes the failure in technical terms, but it is not necessarily useful to a person who entered a filename. The recovery message File cannot be opened: missing.txt tells the user both what happened and which filename caused the problem. The except block gives the program control over that communication.
Mistakes to Avoid
Putting the file-opening operation outside the try block
A failure at the opening point is then not handled by the recovery code.
Fix:
Place the open() attempt inside the try block.Letting the program continue after opening fails
Later code may attempt to use a file that was never opened.
Fix:
Call exit() in the except block when opening the file is critical to the rest of the program.Showing only the raw traceback to the user
Technical traceback details can confuse the user.
Fix:
Print a clear message that explains the file cannot be opened and includes the attempted filename.Assuming every entered filename is valid
The file may not exist or may not be accessible.
Fix:
Treat file opening as a potential failure and handle it with try/except.
Apply the Recovery Pattern
Imagine a program asks the user for a filename and then opens it. Describe what should happen in each case: the file exists, the file does not exist, and the file cannot be accessed. For the failure cases, write the user-facing message and state whether the program should continue or call exit().
Hints
- A successful open assigns the file object and lets later file-processing code run.
- A missing file causes open() to raise FileNotFoundError.
- A critical opening failure should lead to a clear message and exit().
Tracing a Missing Filename
A user enters missing.txt, and the program attempts to open it inside a try block.
Opening attempt: open() attempts to open missing.txt.
Failure: Because the file does not exist, open() raises FileNotFoundError.
Control transfer: Python stops executing the try block and moves to the except block.
Recovery: The program prints File cannot be opened: missing.txt.
Clean termination: exit() prevents the program from reaching file-processing statements after the try/except structure.
The user receives a meaningful message instead of being left with an uncontrolled traceback.
Key Takeaways
- File opening can fail because the requested file does not exist or cannot be accessed.
- A try block contains the operation that may fail, while an except block contains recovery code.
- When open() raises FileNotFoundError, Python stops the try block and moves to except.
- A user-friendly message is more helpful than a raw Python traceback.
- When file opening is critical, call exit() after reporting the failure so later code does not use an unopened file.
Key Takeaways
- Protect file-opening operations with try/except because the requested file may not exist or may not be accessible.
- A successful open lets the program continue; a FileNotFoundError transfers control to the except block.
- Recovery code should explain the problem in language the user can understand and identify the attempted filename.
- Call exit() after a critical opening failure to prevent later code from using a file that was never opened.