File Input and Output
File Input and Output (I/O) is the mechanism by which programs interact with data stored on disk. Without file I/O, your program cannot save work, load configuration, or process stored data.
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…
Why Files Matter in Programs
Every program you write exists in memory only while it runs. Once the program stops, all variables and data disappear. But many real-world programs need to persist data: a banking application must save account balances, a game must store high scores, a data analysis tool must load measurements from yesterday's experiment. This is where files come in. Files are the bridge between your program's temporary memory and permanent storage on disk. The ability to create, read, and write files is essential to many programs.
File Input and Output (I/O) is the mechanism by which programs interact with data stored on disk. Without file I/O, your program cannot save work, load configuration, or process stored data.
The File I/O Workflow
Every interaction with a file follows a predictable sequence. First, your program must open the file, which tells the operating system you want access to it and establishes a connection. Next, your program performs operations: reading data from the file into memory, or writing data from memory into the file. Finally, your program must close the file, which releases the connection and ensures all data is safely written to disk. This three-step pattern—open, operate, close—is fundamental to all file handling.
Opening a File and Choosing a Mode
When you open a file in Python, you must specify a mode that tells the operating system what you intend to do with it. The mode determines whether you can read, write, or both, and critically, what happens to any existing content in the file. Choosing the wrong mode can accidentally erase data or cause your program to fail when it tries to write to a read-only file.
| Mode | Purpose | File Must Exist? | What Happens to Existing Content |
|---|---|---|---|
| r | Read only | Yes | Content is preserved; file pointer starts at beginning |
| w | Write only | No (created if missing) | Existing content is completely erased; file is truncated to zero bytes |
| a | Append | No (created if missing) | Existing content is preserved; file pointer starts at the end |
| r+ | Read and write | Yes | Content is preserved; file pointer starts at beginning |
| w+ | Write and read | No (created if missing) | Existing content is completely erased |
File modes and their behavior: what each mode allows and what happens to the file
The File Pointer and How It Moves
When a file is open, the operating system maintains a file pointer—a position marker that tracks where in the file the next read or write operation will occur. Think of it like a bookmark in a book: it marks your current location. When you read data, the pointer advances past the bytes you just read. When you write data, the pointer advances past the bytes you just wrote. Understanding the pointer's position is crucial because it determines what data you will read next or where new data will be written.
In read mode, the pointer starts at byte 0 (the beginning). Each read operation advances the pointer. In append mode, the pointer starts at the end of the file. In write mode, the file is empty, so the pointer starts at byte 0.
Context Managers: Safe File Handling
Python provides a feature called a context manager, invoked using the 'with' statement, that automatically handles opening and closing files. When you use 'with', Python guarantees that the file will be closed at the end of the block, even if an error occurs. This prevents resource leaks and ensures data is written to disk. Without a context manager, you must manually close the file, and if your code crashes before the close statement, the file remains open and data may be lost.
Always use the 'with' statement when working with files. It is the standard Python idiom and eliminates the risk of forgetting to close a file. Reserve manual open() and close() calls only for advanced scenarios where you need fine-grained control over the file's lifetime.
Reading File Content
Python provides several methods to read data from a file, each suited to different situations. The read() method reads the entire file into a single string, useful for small files but wasteful for large ones. The readline() method reads one line at a time, advancing the file pointer after each call. The readlines() method reads all lines into a list of strings. The most Pythonic approach is to iterate directly over the file object, which yields one line at a time without loading the entire file into memory.
Reading a File Line by Line
You have a file named 'scores.txt' containing three lines: '85', '92', '78'. Write code to read the file and print each score.
- 1Open the file in read mode
Use the 'with' statement and
open()with mode 'r'. The file object is assigned to the variable 'f'. - 2Iterate over the file object
When you iterate directly over an open file, Python yields one line at a time. The newline character at the end of each line is included in the string.
- 3Strip whitespace and print
Use the
strip()method to remove the trailing newline, then print the cleaned line. - 4File automatically closes
When the 'with' block ends, Python automatically closes the file, even if the loop completes or an error occurs.
The output is: 85, 92, 78 (each on a separate line), and the file is safely closed.
85
92
78Writing and Appending Data
Writing to a file is similar to reading, but uses the write() method instead of read(). The write() method takes a string and writes it to the file at the current file pointer position. In write mode ('w'), the file is truncated first, so the pointer starts at byte 0 and any new data overwrites from the beginning. In append mode ('a'), the pointer starts at the end, so new data is added after existing content. Remember that write() does not automatically add newlines; you must include '\n' in your string if you want line breaks.
Writing to a File
Create a file named 'log.txt' and write three log messages, each on a separate line.
- 1Open the file in write mode
Use 'with
open('log.txt', 'w')'. Since the file doesn't exist, it is created. If it did exist, its content would be erased. - 2Write the first message
Call
f.write()with the string 'Starting program\n'. The \n is essential; without it, all messages would be on one line. - 3Write the second and third messages
Call
f.write()twice more with the remaining messages, each ending with \n. - 4File closes and data is saved
When the 'with' block ends, the file is closed and all written data is flushed to disk.
The file 'log.txt' now contains three lines: 'Starting program', 'Processing data', 'Finished'.
To add data to an existing file without erasing it, use append mode ('a'). The file pointer starts at the end, so new data is added after the existing content. This is useful for log files where you want to record events over time without losing previous entries.
Common Mistakes with File I/O
Common mistake Forgetting to close the file after manual open()
What it looks likef = open('data.txt', 'r') data = f.read() print(data)Why it failsThe file remains open, consuming system resources. If the program crashes or runs for a long time, the operating system may run out of available file handles. Additionally, if you later try to write to the same file from another part of your program, the changes may not be visible because the file is still held open.
Do this insteadUse the 'with' statement: with open('data.txt', 'r') as f: data = f.read()
Common mistake Using write mode ('w') when you meant to append
What it looks likewith open('log.txt', 'w') as f: f.write('New entry\n')Why it failsIf '
log.txt' already exists with previous entries, opening it in write mode immediately erases all existing content. You lose all historical data.Do this insteadUse append mode ('a') instead: with open('log.txt', 'a') as f:
Common mistake Trying to read from a file that doesn't exist
What it looks likewith open('missing.txt', 'r') as f: data = f.read()Why it failsOpening a non-existent file in read mode raises a
FileNotFoundError. Your program crashes unless you handle the exception.Do this insteadCheck if the file exists first, or use try/except to catch the error. Alternatively, use mode 'r+' or 'a' which create the file if it doesn't exist.
Common mistake Forgetting to strip newlines when reading lines
What it looks likewith open('data.txt', 'r') as f: for line in f: print(line)Why it failsEach line read from the file includes the trailing newline character. When you print it, you get an extra blank line because
print()also adds a newline by default.Do this insteadUse strip(): print(line.strip())Common mistake Not including newlines in write() calls
What it looks likewith open('output.txt', 'w') as f: f.write('Line 1') f.write('Line 2') f.write('Line 3')Why it failsAll three lines are written consecutively without line breaks, resulting in 'Line 1Line 2Line 3' on a single line in the file.
Do this insteadAdd '\n' to each write(): f.write('Line 1\n')
Choosing the Right Approach for Your Task
| Task | Best Method | Why |
|---|---|---|
| Read a small file all at once | read() | Simple and fast for files that fit in memory |
| Process a large file line by line | Iterate over file object | Memory-efficient; only one line is in memory at a time |
| Read all lines into a list | readlines() | Useful if you need random access to lines or want to process them in a specific order |
| Create a new file or overwrite existing | Mode 'w' | Clears the file and starts fresh |
| Add data to an existing file | Mode 'a' | Preserves existing content and appends new data at the end |
| Read and write to the same file | Mode 'r+' or 'w+' | Allows both operations; 'r+' preserves content, 'w+' truncates |
Choosing the right file I/O method for common tasks
Practice: Building a Simple Data Logger
Write a program that simulates a simple data logger. Your program should: (1) Open a file named 'sensor_data.txt' in append mode, (2) Write three simulated sensor readings to the file, each on a separate line, with the format 'Temperature: X degrees', (3) Close the file, (4) Open the file again in read mode and print all the readings. Use the 'with' statement for all file operations. After running your program twice, verify that the file contains six readings (three from each run), not just three.
Hints
- Remember to include '\n' at the end of each line you write
- Use append mode ('a') so that the second run adds to the file rather than overwriting it
- Iterate directly over the file object when reading, or use
readlines() - Strip newlines when printing to avoid extra blank lines
Summary
- 1File I/O follows a three-step pattern: open the file, perform read or write operations, and close the file. The 'with' statement automates the closing step and ensures safe resource cleanup.
- 2File modes determine what operations are allowed and what happens to existing content. Mode 'r' reads only, 'w' writes and erases existing content, 'a' appends to the end, and 'r+' and 'w+' allow both reading and writing.
- 3The file pointer is a position marker that tracks where the next read or write will occur. It starts at byte 0 in read and write modes, and at the end of the file in append mode. Each read or write operation advances the pointer.
- 4Python provides multiple ways to read files:
read()for the entire file,readline()for one line at a time,readlines()for all lines as a list, and direct iteration for memory-efficient line-by-line processing. - 5Always use the 'with' statement to open files. It is the standard Python idiom, prevents resource leaks, and handles errors gracefully. Never forget to include newline characters ('\n') when writing multiple lines.
At a glance
- File I/O is the mechanism by which programs interact with persistent data on disk. Every file operation follows the pattern: open, operate, close.
- File modes control what operations are allowed and what happens to existing content. Write mode ('w') erases the file; append mode ('a') adds to the end; read mode ('r') reads only.
- Use the 'with' statement to safely open and close files. It automatically closes the file even if an error occurs, preventing resource leaks and data loss.
- The file pointer tracks the current position in the file. It advances with each read or write operation, determining where the next operation will occur.
- Choose your read method based on your needs:
read()for small files, iteration for large files, andreadlines()when you need random access to lines.