8.1 Opening and Closing a File
You cannot read a book that is still on the shelf — you have to take it down and open it first. A file works the same way. Before your program can touch a single character of a file, it must ask the operating system to open it, and it must say why it wants it (to read? to write?). Get this one line right and everything else in the chapter follows from it.
Python opens a file with the built-in open() function. It takes two things: the filename and the mode. It hands back a file handle — a variable you use for every later operation on that file.
file = open("data.txt", "r") # filename, then mode
# ... read or write here ...
file.close() # always release the fileThe mode is a one-letter string. There are exactly three you need for Paper 4, and the difference between them is the single most common source of lost marks in file questions:
| Mode | Name | If file does NOT exist | If file DOES exist |
|---|---|---|---|
"r" | Read | Crashes (FileNotFoundError) | Keeps contents — opens for reading only |
"w" | Write | Creates a new empty file | Wipes contents instantly on open |
"a" | Append | Creates a new empty file | Keeps contents — new writes go at the end |
"r"— read. The file must already exist. If it does not, Python crashes withFileNotFoundError. Why? Because there is nothing to read."w"— write. Creates the file if it does not exist. If it does exist, all existing content is wiped instantly, the moment the file opens — before you write anything."a"— append. Creates the file if needed, but if it exists, the existing content is kept and new writes go on the end. Logs, registers and records grow — you add to them, you do not retype them.
- Opening an existing file in
"w"mode erases everything in it immediately. - If the question says "add to the file" or "keep the existing data", you must use
"a". - Choosing the wrong one is a logic error the examiner will spot at once.
And why does close() matter? Two reasons. First, written data is often held in a memory buffer and only physically saved to disk when the file closes — forget to close and your file can end up empty. Second, an open file is locked: other programs (or another part of your own program) may not be able to use it. Open, do the job, close. Every time.
- In real Paper 4 mark schemes, "opening the file in the correct mode" and "closing the file in an appropriate place" are each worth their own mark — see 9618/42 M/J 2024 Q1(a) and 9618/42 O/N 2022 Q2(d).
- Two marks are sitting there for two short lines of code.
- Never leave them out.
- When the question gives you the filename as a parameter (e.g.
def ReadData(filename):), use the parameter inopen(filename, "r")— do not hard-code"data.txt". - Mark schemes specifically award "opening file using parameter filename".
Opening & Closing a File
8.2 Writing to a File
Every useful system you have ever used saves something — your game saves progress, your school saves your marks, your phone saves messages. Writing to a file is how a program turns its temporary results into a permanent record. This is also the easiest mode to start with, because there is nothing to read: you create the file yourself.
Open the file in "w" mode and call write() on the handle. One detail trips everyone up: write() does not move to a new line by itself, the way print() does. If you want each item on its own line — and in Paper 4 you almost always do — you must add the newline character "\n" yourself.
file = open("greeting.txt", "w") # creates the file (or wipes it)
file.write("Hello, world!\n") # \n ends the line
file.write("Welcome to Paper 4.\n")
file.close() # data is now safely on diskThe file greeting.txt will contain:
Hello, world!
Welcome to Paper 4.One more rule that costs marks: write() accepts strings only. If you try file.write(75) Python crashes with a TypeError, because a file is a sequence of characters and 75 is a number, not characters. Convert first: file.write(str(75) + "\\n").
str(), and every line must end with + "\\n" if you want the next write to start on a new line.- Choose the mode — we are creating a brand-new file, so open in "w" mode
- Write each name with \n — three write() calls, each ending in "\n"
- Close the file — this flushes the buffer so the names are physically saved
- Identical structure to the worked example: open in "w"
- Three write() calls each ending in "\n"
- Then close()
- Numbers must be converted with str() before writing
- write(str(number) + "\n") for each value
- Open in "w" mode and close at the end
- Use write(str(number) + "\n") for each value
- Open prices.txt in "w" mode
- Close the file at the end
- input() already returns a string, so no str() is needed
- Just add "\n" so any future append starts on a new line
- Open in "w" mode and close at the end
- Same three lines; only the prompt and filename change
- input() returns a string — add "\n" when writing
- Open food.txt in "w" mode
- In Paper 4, writing output to a file is usually the final part of a question and is marked per operation: open in the correct mode, write the correct data with a newline, close the file.
- Examiners accept
file.write(str(n) + "\\n")or an f-string likefile.write(f'{n}\n')— both earn the mark.
Writing to a File
8.3 Reading from a File
This is the skill Paper 4 tests most. The exam gives you a ready-made data file — names, scores, stock records — and your very first job is to get that data out of the file and into your program. If you can read a file line by line confidently, you can start every file question on the paper.
There are two ways to read, and you should know when to use each:
1. Read everything at once with read(). This returns the whole file as one big string. It is fine for simply displaying a file, but useless when you need to process items one at a time.
file = open("register.txt", "r")
content = file.read() # the entire file as ONE string
print(content)
file.close()2. Loop line by line. This is the Paper 4 way. Python lets you put the file handle straight into a for loop — each pass of the loop gives you the next line, and the loop stops automatically at the end of the file (EOF). No counting, no checking — Python handles EOF for you.
file = open("register.txt", "r")
for line in file: # one line per loop pass, stops at EOF
print(line.strip()) # .strip() removes the invisible \n
file.close()Output (assuming register.txt contains Musarrat, Tarnima, Aymaan):
Musarrat
Tarnima
AymaanWhy .strip()? Remember that every line in the file ends with an invisible \n. When Python reads the line, that \n comes along with it. If you print without stripping, you get the line's own \n plus print's newline — double spacing. Worse, if you compare line == "Musarrat" it will be False, because the line is actually "Musarrat\n". Strip first, always.
- Every line you read carries a hidden
\n— remove it with.strip()before you compare, convert or store it. int("85\n")happens to work, but"Musarrat\n" == "Musarrat"is False, and stored lines with stray newlines corrupt your output later.- Make
line.strip()a reflex.
- Open in "r" mode — we are only reading, and the file already exists
- Loop line by line — for line in file: hands us each line and stops at EOF
- Strip before using — without .strip() the output would be split across two lines
- Same four-line pattern: open "r"
- for line in file:
- strip
- print with the message joined on
- Strip first, then test len(word)
- Testing len(line) would count the hidden \n too
- Use if len(word) > 5: print(word)
- Strip each line first
- Use len(name) > 4 inside the loop
- print(name) when the test is true
- Initialise count = 0 before the loop
- Add 1 per line inside the loop
- You do not even need .strip() just to count
- Identical counter pattern
- You do not even need .strip() just to count
- count = 0 before the loop, count = count + 1 inside
- Examiners award a mark for "removing the carriage return / newline from each line read in" — that is the
.strip()mark. - They also award a mark for the loop itself reading until EOF; in Python,
for line in file:earns it automatically. - Two marks for two habits.
Reading from a File
8.4 Appending to a File
Think about a school attendance log. Each day you add today's record — you do not retype the whole year. That is exactly what append mode is for: keep everything already in the file and add new lines to the end. If you used "w" instead, day 2 would erase day 1. Real systems — logs, registers, transaction histories — live and die by this distinction.
Open in "a" mode. Everything else — write(), str(), "\n", close() — works exactly as in section 8.2. The only change is where the new text lands: at the end of the existing content instead of replacing it.
file = open("register.txt", "a") # existing names are KEPT
file.write("Mehrin\n") # added after the last line
file.close()If register.txt previously contained Musarrat, Tarnima, Aymaan, after running this it contains:
Musarrat
Tarnima
Aymaan
Mehrin- Read the requirement: "adds to the end... without losing" → append mode
- "w" would be wrong here — it would lose marks and the data
- input() gives a string; add "\n" so the next append starts on a fresh line
- Three lines after the input()
- open with "a"
- write with "\n", close
- Open scores.txt in "a" mode
- write(str(91) + "\n")
- close()
- Open "a" mode
- write(str(250) + "\n")
- close()
- The verbs "add", "record" or "keep existing" always mean append.
- The verbs "create" or "output the results to a new file" mean write.
- The mode mark is awarded or lost on this single word.
Appending to a File
8.5 The with Statement
Forgetting close() is the most common file bug there is — and it can silently leave your file empty or locked. Python gives you a pattern that makes the mistake impossible: with opens the file and guarantees it closes when the indented block ends, even if the program crashes mid-way. Professional Python code uses it everywhere, and it is fully accepted in Paper 4.
with open("register.txt", "r") as file: # opens, names the handle "file"
for line in file:
print(line.strip())
# the block has ended -- the file is ALREADY closed hereRead it as a sentence: "with this file open as file, do the following." Everything indented under the with line happens while the file is open. The instant the indentation ends, Python closes the file for you — no close() call, no way to forget it.
open()…close()andwith open()…earn the same marks — real mark schemes note the close "might be within the Python opening file statement", meaning the with version.- Pick one style and use it consistently; just never write open() without a matching close().
- Merge open() into the with line: with open("register.txt", "r") as file:
- Indent the reading and printing inside the block
- Delete close() — it is no longer needed
- The mode "a" goes inside the with line exactly where it went inside open()
- Indent the write() call inside the block
- Delete close()
- If a question gives you a partial program already using open()/close(), continue in that style — do not mix the two in one answer.
- Consistency reads as confidence to an examiner; a with block that also calls close() reads as confusion.
The with Statement
8.6 Text Files + Arrays: Loading and Saving a List
A file on disk is slow and can only be read forwards, line by line. A list in memory is fast and lets you jump to any element, sort, search and count. So every serious Paper 4 program follows the same plan: read the file into a list once, do all the work on the list, write results back at the end. This section is the bridge between Chapter 4 (lists) and everything the exam will throw at you.
Loading a file into a list is the read loop from 8.3 plus one extra line: instead of printing each cleaned line, append() it to a list you created empty before the loop.
numbers = [] # 1. start with an empty list
file = open("numbers.txt", "r") # 2. open to read
for line in file: # 3. one line per pass, stops at EOF
numbers.append(int(line.strip())) # 4. clean, convert, store
file.close() # 5. release the file
print(numbers) # [10, 20, 30, 40, 50]If numbers.txt contains 10, 20, 30, 40, 50, the output is:
[10, 20, 30, 40, 50]Look closely at line 4 — it does three jobs, inside-out: line.strip() removes the newline, int(…) converts the text "10" into the number 10, and numbers.append(…) stores it. Why convert? Because a file can only hold characters. The file contains the two characters "1" and "0", not the number ten. Until you convert, "10" + "20" gives "1020" — string joining, not addition.
- Reading numbers? Convert with
int()orfloat()as you load them. - Reading names?
.strip()is enough. - Forgetting the conversion is the classic cause of "my total is 1020 instead of 30".
- This exact pattern — declare array, open file, loop to EOF, read each line, store in the array, close file — is the published mark scheme breakdown of 9618/42 M/J 2024 Q1(a), where each step listed is worth one mark.
- Learn the five-step skeleton above and you can write it for any file the exam gives you.
Saving a list to a file is the mirror image: loop through the list and write each element with str() and "\n".
numbers = [10, 20, 30, 40, 50]
file = open("output.txt", "w")
for n in numbers:
file.write(str(n) + "\n")
file.close()- Load with the five-step skeleton: empty list, open "r", loop, strip + int + append, close
- Work on the list, not the file — the file is already closed
- Totalling is pure list work from Chapter 4
- Load exactly as in the worked example
- Then average = total / len(list)
- Sum the list with the same total accumulator pattern
- Same 5-step skeleton but no int() this time
- Names and words need .strip() only
- append(line.strip()) inside the loop
- .strip() removes the newline from each colour
- No conversion needed — they stay as strings
- Five-step skeleton with append(line.strip())
- The saving loop: str() out, just as int() came in
- Open output.txt in "w" mode
- Loop the list, write str(v) + "\n"
- Names are already strings
- write(name + "\n") — no str() needed
- Open team.txt in "w" mode
- When a question says the file contains a known number of items (e.g. "the file stores 10 records"),
for i in range(10):withfile.readline()is also accepted — mark schemes credit "looping until EOF / 10 times" as alternatives. - When the count is unknown, only the EOF loop works.
Text Files + Arrays
8.7 Processing File Data
Loading a file is never the whole question — it is the setup. The marks come from what you do next: count the values that meet a condition, split them into groups, find the largest, merge two sources. Each of these is a small pattern you already met in Chapters 3 and 4, now fed by file data instead of typed input. This section drills the four patterns the exam recycles again and again.
Pattern 1 — count with a condition
nums = []
file = open("numbers.txt", "r")
for line in file:
nums.append(int(line.strip()))
file.close()
pos = 0
neg = 0
for n in nums:
if n > 0:
pos = pos + 1
elif n < 0:
neg = neg + 1
print("Positive:", pos)
print("Negative:", neg)If numbers.txt contains -5, 12, -8, 0, 3, -1, the output is:
Positive: 2
Negative: 3Notice that 0 is counted by neither branch — the elif chain deliberately lets it fall through. Always check what the question wants done with boundary values.
Pattern 2 — split into two lists
nums = []
file = open("numbers.txt", "r")
for line in file:
nums.append(int(line.strip()))
file.close()
even = []
odd = []
for n in nums:
if n % 2 == 0:
even.append(n)
else:
odd.append(n)
print("Even:", even)
print("Odd:", odd)Pattern 3 — file in, two files out
Combine pattern 2 with the saving loop from 8.6: after splitting, write each list to its own file.
nums = []
file = open("numbers.txt", "r")
for line in file:
nums.append(int(line.strip()))
file.close()
evenFile = open("even.txt", "w")
oddFile = open("odd.txt", "w")
for n in nums:
if n % 2 == 0:
evenFile.write(str(n) + "\n")
else:
oddFile.write(str(n) + "\n")
evenFile.close()
oddFile.close()Two files can be open at the same time — as long as each has its own handle and each gets its own close().
Pattern 4 — combine two files into one list
data1 = []
file1 = open("file1.txt", "r")
for line in file1:
data1.append(int(line.strip()))
file1.close()
data2 = []
file2 = open("file2.txt", "r")
for line in file2:
data2.append(int(line.strip()))
file2.close()
combined = data1 + data2 # + joins two lists end to end
print(combined)- Load in one loop, process in another, save in a third.
- Beginners try to read, test and write inside a single loop and tie themselves in knots.
- Separate loops are easier to write, easier to trace, and match how mark schemes award the marks step by step.
- Load — the five-step skeleton from 8.6 fills the list scores
- Process — Python's built-ins max() and min() scan the list for us
- Save — open summary.txt in "w" mode (the question says a NEW file)
- Write both lines, converting numbers with str()
- Identical three-phase structure
- Load skeleton, then max() / min()
- Write two lines to "report.txt" in "w" mode
- Pattern 1 with a different condition
- above = 0, below = 0 before the loop
- if s > 50 → above; elif s < 50 → below
- A score of exactly 50 is counted by neither — as the question implies
- This time the two conditions cover everything
- if age >= 18 … else …
- adults = 0, minors = 0 before the loop
- Pattern 3 — two output handles, two closes
- evenFile and oddFile both opened in "w" mode
- Test: if n % 2 == 0 → evenFile, else → oddFile
- Same shape as 7.7C
- The test becomes if m >= 75
- Two output handles: dFile and sFile
- Pattern 4 plus the saving loop
- Three files touched; each opened, used, closed
- combined = data1 + data2
- Names need .strip() only
- The combine and save steps are identical to 7.7D
- combined = g11 + g12; write each name + "\n"
- In a multi-file program, give every handle a meaningful name (
evenFile,out) instead of reusingfilewhile another file is still open. - Reused handles are the top cause of "file written to the wrong place" errors under exam pressure — and they make your code harder for the examiner to follow.
Processing File Data
8.8 Full Exam-Style Question
Everything above was drilled one skill at a time. The real paper hands you one scenario and makes you chain the skills: read a file into a global array, process the array, write results out. Attempt this under timed conditions (about 18 minutes) before opening the mark scheme.
- A school stores the results of a Computer Science test in the text file
results.txt. - Each line of the file contains one mark as an integer.
- The number of lines in the file is unknown.
The program uses the global variables:
marks = [] # global 1D array of integers
numberMarks = 0 # global integer, the number of marks read(a) ReadMarks(fileName) — [6 marks] AO3
Write the Python function ReadMarks(fileName) that takes the name of the file as a parameter, reads every mark from the file into the global array marks, stores the number of marks read in numberMarks, and returns numberMarks.
(b) CountDistinctions() — [3 marks] AO3
Write the Python function CountDistinctions() that returns the number of marks in the array that are greater than or equal to 75.
(c) SaveSummary() — [4 marks] AO3
Write the Python procedure SaveSummary() that writes two lines to a new text file summary.txt:
- the first line contains the number of marks, in the form
Total: 25 - the second line contains the number of distinctions, in the form
Distinctions: 7
Your procedure should call CountDistinctions().
(d) Why is "w" wrong? — [1 mark] AO1
State one reason why opening results.txt in "w" mode in part (a) would be incorrect.
Total: 14 marks
- Part (a) is the 5-step skeleton plus the "global" twist
- Part (b) — use >= 75 (not > 75)
- Part (c) — open in "w" mode (the stem says "a new file")
- Part (d) — any ONE reason: "w" wipes the file / "w" opens for writing so marks cannot be read
- Part (a) is six marks for the five-step skeleton you drilled in 8.6 plus one twist:
global. - When a Paper 4 question says the array and counter are global, you must write
global marks, numberMarksas the first line inside the function before assigning to them — omitting it makesnumberMarks = numberMarks + 1crash in Python, and the mark scheme expects it.
Full Exam-Style Question
✓ Key Points Summary
8.9 Practice Tasks
Fifteen exam-style file-handling tasks. Each has a Hint (thought process, bullet points) and a Help button (full Python solution). Try the task first, use the Hint if you are stuck, then check the Help to verify.
Question Bank
Answer all questions, then press Submit Quiz to see your score.
Question 1Multiple Choice
What is the correct way to open data.txt for reading?
Question 2Multiple Choice
You call file.write(50) on a freshly opened file. What happens?
Question 3True / False
Calling file.write("Hello") automatically moves the cursor to the next line.
Question 4Multiple Choice
A file register.txt contains the name "Musarrat" on its own line. You read it with for line in file: and compare line == "Musarrat". What is the result?
Question 5Multiple Choice
A question stem says: "Add the new sale to the end of sales.txt, keeping the existing sales." Which mode and which conversion are needed?
Question 6True / False
The with statement closes the file for you automatically when the indented block ends, even if the program crashes mid-way.
Question 7Multiple Choice
Which snippet correctly loads a file of integers into a list using the 5-step skeleton?
Question 8Multiple Choice
A file temps.txt contains 5 temperature readings. Which code finds the average?
Question 9True / False
In a program that writes even numbers to even.txt and odd numbers to odd.txt, you can keep both files open at the same time using two separate handles.
Question 10Multiple Choice
A question says "create a NEW file summary.txt and write the total marks to it". Which mode is correct?
Question 11True / False
In CountDistinctions() the test m > 75 is correct because the question says "75 or more".
Question 12Multiple Choice
You have data1 = [1, 2, 3] and data2 = [4, 5, 6] loaded from two files. What does data1 + data2 give?
Answer all 12 questions to enable submission.