Loops and Conditionals
The central pattern is: obtain a file name, open the file safely, loop through its lines, apply string operations, and use a condition when only some lines should be selected.
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…
From Filename to Lines
File processing becomes useful when several small programming actions work together. A program can ask the user which file to process, open that file, visit its contents one line at a time, transform each line, and select only the lines that match a pattern. Loops provide repetition, while conditionals provide decisions about individual lines.
The central pattern is: obtain a file name, open the file safely, loop through its lines, apply string operations, and use a condition when only some lines should be selected.
First Pass Through the File
A for loop can process a file one line at a time. On each pass, the loop provides the next line for the program to process. The same operation can therefore be applied repeatedly without writing a separate instruction for every line. After the available lines have been processed, the loop stops.
In this generated example, the with statement is used for the file operation, and the for loop receives each line in turn. The rstrip() call removes the line-ending characters before printing, which avoids the extra blank lines that can occur when a line already contains a newline character.
Transforming Each Line
A loop does not have to print a line exactly as it was read. Inside the loop, string methods can transform the current line. For example, upper() can convert the line's text to uppercase before it is displayed or used elsewhere.
The current line is transformed with upper() and then cleaned with rstrip() before printing. The order makes the purpose of each string operation visible: one changes the letter case, and the other handles the newline at the end of the line.
Filtering Matching Lines
A conditional lets the program decide what to do with each line. The string method startswith() can test whether a line begins with a chosen pattern. If the test matches, the program can print or transform that line; if it does not match, the program can continue to the next line.
Here, every line is examined, but only lines beginning with the generated pattern ERROR: are displayed. The loop still controls repetition, while the if statement controls selection within each repetition.
Complete File-Processing Pattern
The separate techniques can be combined into one end-to-end program. The input() call makes the file choice dynamic: instead of placing a fixed file name in the program, the program uses the user's response directly with open(). The loop then searches for matching lines and transforms the selected text.
filename = input("Enter a file name: ")
with open(filename) as file:
for line in file:
if line.startswith("ERROR:"):
print(line.upper().rstrip())- 1
input()asks the user for a file name and stores the response in filename. - 2
open(filename)uses that response to select the file. - 3The for loop reads the selected file line by line.
- 4
startswith("ERROR:")checks whether the current line begins with the target pattern. - 5
upper()transforms matching text, andrstrip()handles the line-ending character beforeprint()displays it.
Tracing the Combined Program
Suppose the selected file contains three lines: INFO: Started, ERROR: Missing value, and INFO: Finished. Which line is displayed by the generated program, and how is it transformed?
- 1Read the first line
The line begins with INFO:, so it does not satisfy the
startswith("ERROR:")condition. - 2Read the second line
The line begins with ERROR:, so the condition succeeds.
- 3Transform the match
The matching line is converted to uppercase and its trailing newline is removed before printing.
- 4Read the third line
The line begins with INFO:, so it is not displayed.
The displayed result is ERROR: MISSING VALUE.
Mistakes in File Loops
Common mistake Using a fixed file name when the program should respond to user input
What it looks likewith open("notes.txt") as file:Why it failsThe program always selects the same file instead of using the file name supplied by the user.
Do this insteadStore input() in a variable and pass that variable directly to open().
Common mistake Printing a file line without handling its newline character
What it looks likeprint(line)Why it failsThe line already includes a newline character, and
print()can add another line ending, producing extra blank lines.Do this insteadUse line.rstrip() or adjust the print() call.Common mistake Applying the condition outside the line-processing loop
What it looks likeThe program opens the file but does not test each line inside the for loop.
Why it failsPattern searching must be performed on each individual line as the loop processes it.
Do this insteadPlace the startswith() test inside the for loop.
Common mistake Opening a file without a with statement
What it looks likefile = open(filename)Why it failsThe source material emphasizes using with so file operations are handled safely and the file is properly closed.
Do this insteadUse with open(filename) as file: and place the processing code inside the block.
Consider what the program should communicate when the file is empty or when no line matches the selected pattern. The source material specifically encourages attention to empty files, unusual formatting, and clear feedback to the user. These cases do not change the loop-and-condition structure, but they affect how understandable the program feels when it produces no matching output.
Practice: Build the Search
Write a program that asks the user for a file name, opens the selected file with a with statement, and checks every line for the pattern TODO:. Display matching lines in uppercase without producing extra blank lines.
Hints
- Store the result of
input()in a variable and pass that variable toopen(). - Place a for loop inside the with block.
- Use
startswith("TODO:")inside an if statement. - Combine
upper()withrstrip()when displaying a matching line.
Key Takeaways
- 1A for loop processes a file one line at a time.
- 2String methods such as
upper()can transform each line during iteration. - 3
input()can provide a file name that is passed directly toopen(). - 4
startswith()can select only lines that begin with a chosen pattern. - 5
rstrip()helps prevent extra blank lines when printing file contents, and with helps ensure file operations are handled safely.
At a glance
- Use a for loop to read and process file contents line by line.
- Apply string methods such as
upper()to transform the current line. - Use
input()withopen()when the user should choose the file dynamically. - Use
startswith()inside a conditional to search for matching lines. - Use a with statement and handle newline characters carefully when displaying results.