Opening Files and Getting File Handles
Attempting to open a non-existent file raises a FileNotFoundError and prevents the program from obtaining a file handle.
Try it: Reading and Writing Text Files
How open() returns a file object with a position pointer, how read(), read(n), readline(), readlines() and for line in fh advance it (and return '' at the end), how 'w' and 'a' modes change the file, and why a closed file (after close() or a with block) can no longer be read.
How it works
- open(name, 'r') starts the pointer at 0; 'w' empties the file first; 'a' starts at the end.
- read() returns everything from the pointer to the end; read(n) at most n characters; readline() up to and including the next \n; each moves the pointer past what it returned.
- At the end of the file every read returns '' (an empty string), which is how loops know to stop; for line in fh reads line by line the same way.
- write() text waits in a buffer and reaches the file when it is closed (or the program ends); reading a 'w'/'a' file or writing an 'r' file raises io.UnsupportedOperation.
- close(), or leaving a with block, closes the file; any further read raises ValueError: I/O operation on closed file.
Default run (10 steps): Ready: notes.txt holds 4 lines (51 characters). Nothing is open yet. … Finished. notes.txt now holds "From: stephen\nSubject: meeting\nFrom: louis\nThanks!\n".
Simplified: The lab's own small Python interpreter runs a fixed, hand-written script (you choose the variant and the values, never the code); nothing is executed as real Python. Every script was run in CPython 3.12 with the same inputs and the lab reproduces its output and error messages. One virtual text file with \n line endings (as on Linux/macOS), positions counted in characters (ASCII only), and a write buffer that is only flushed by close() or the end of the program.
Loading the simulation…
The Failed Opening
When a program calls open() for a file that is not where the program expects it to be, Python cannot obtain a file handle. Instead, it raises FileNotFoundError. Without error handling, execution stops at the failed call, so statements after it do not run.
What do you think happens?
Suppose the file does not exist. Which statement runs: the statement immediately after open(), or an error-handling statement in an except block?
Reveal answer
The matching except block, if one exists. Without a matching except block, execution stops and the later statement does not run.
A failed operation inside a try block transfers control to its matching except block. If the failure is not caught, Python stops execution and displays a traceback.
Control Flow Without Handling
In this example, the call to open() is the point of failure when missing_notes.txt does not exist. Python does not assign a file handle to file_handle. Because the error is not caught, the print() statement is never reached, and the program terminates with a traceback.
Reading the Traceback
A traceback is the error information Python displays when the failure is not handled. It identifies where the failure occurred, shows the code that failed, and names the error type as FileNotFoundError. The error means that Python looked for the requested file but did not find it where the program said it would be.
- The opening part indicates that a traceback is being reported.
- The location information identifies the file and line where the failure occurred.
- The code information shows the statement that failed.
- The final error information names
FileNotFoundErrorand gives details about the missing file.
Handling the Failure
A try statement marks code that might fail. A matching except statement provides the response when that code raises the specified error. If open() raises FileNotFoundError inside the try block, Python jumps to the matching except block. After the except block finishes, execution continues normally.
The file was not found
The program continuesThe first print() inside the try block is skipped because the failure occurs before it. Control moves directly to except FileNotFoundError. The handler prints its message, and then the final print() runs because the error has been handled rather than left uncaught.
Handle or No Handle
The important state change is whether the program obtains a file handle. When the requested file is available, open() can provide a handle for the program to use. When the file is missing, FileNotFoundError occurs instead, so no file handle is obtained from that call.
Following a Missing-File Attempt
Predict the execution order when open() cannot find the requested file.
- 1Step 1
Python enters the try block and attempts to call
open(). - 2Step 2
The requested file is not found, so
open()raisesFileNotFoundErrorinstead of producing a file handle. - 3Step 3
Python skips the remaining statements in the try block and enters the matching except block.
- 4Step 4
After the except block completes, Python continues with statements that follow the try and except structure.
The error-handling response runs, the remaining statements in the failed try block do not run, and later program execution can continue.
Common Mistakes
Common mistake Assuming that every open() call produces a file handle.
What it looks likefile_handle = open("missing_notes.txt")Why it failsIf the requested file does not exist,
open()raisesFileNotFoundErrorand no handle is obtained.Do this insteadConsider that opening can fail, and place the call in a try block when the failure should be handled.
Common mistake Expecting statements after an uncaught open() failure to run.
What it looks likeopen("missing_notes.txt") print("Finished")Why it failsAn uncaught
FileNotFoundErrorstops execution immediately.Do this insteadUse a matching except FileNotFoundError block if the program should respond and continue.
Common mistake Treating the traceback as a syntax error.
What it looks likeThe code is syntactically valid, but the requested file is missing while the program runs.
Why it failsFileNotFoundErroris a runtime error caused by the unavailable file, not by invalid Python syntax.Do this insteadRead the traceback for the failed line and the error type, then decide whether to handle the missing file.
Common mistake Putting the file-opening call outside the try block.
What it looks likefile_handle = open("missing_notes.txt") try: print("Handling the problem") except FileNotFoundError: print("Not found")Why it failsThe failure occurs before Python enters the try block, so that except block cannot handle this call.
Do this insteadPut the operation that might raise FileNotFoundError inside the try block.
Practice the Branch
A program tries to open a file that is not present. It has a try block containing open(), an except FileNotFoundError block that prints a message, and a final print() statement after the handler. Predict which messages appear and explain why.
Hints
- The failed
open()prevents later statements in the same try block from running. - A matching except block receives control when
FileNotFoundErroris raised. - Execution can continue after the except block finishes.
Treat FileNotFoundError as a normal possibility when a program depends on a file. Files can be deleted, moved, renamed, or never created, so a robust program should decide how to respond instead of allowing an unexpected traceback to terminate execution.
Key Takeaways
- 1Calling
open()for a missing file raisesFileNotFoundErrorand does not provide a file handle. - 2Without handling, the error stops execution and displays a traceback.
- 3The traceback identifies the failure location, the failed code, and the
FileNotFoundErrortype. - 4A try block contains the operation that might fail, while a matching except block defines the response.
- 5After the except block completes, execution can continue with later statements.
At a glance
- A missing file prevents
open()from obtaining a file handle and raisesFileNotFoundError. - An uncaught
FileNotFoundErrorstops the program at the failedopen()call. - A traceback explains where the failure occurred and identifies the error type.
- try and except redirect control to an error handler and allow execution to continue afterward.