Start with the study notes on File Handling (definitions, examples and a quick revision), then work through 30 practice questions, each with the correct answer and a clear explanation of why it is right. When you are ready, take this topic as an interactive quiz to test yourself.
10 easy Β· 14 medium Β· 6 hard Β· Part of Python: Master Python from basics to advanced - 20 topics.
Topic overview
File Handling β reading and writing files
1. Opening a file
open(path, mode) returns a file object. The mode says what you want to do:
"r"read (the default); the file must exist.
"w"write; this erases the file first.
"a"append; adds to the end, keeping old content.
"x"create; fails if the file already exists.
"r+" read and write; add "b" for binary files, e.g. "rb" for images.
Remember: Opening an existing file with "w" wipes it immediately, even if you write nothing. Use "a" to add to it.
2. Use with to close files automatically
The with statement closes the file when the block ends, even if an error happens. It is the recommended way to work with files.
with open("notes.txt", "w", encoding="utf-8") as f:
f.write("first line\n")
f.write("second line\n")
print(f.closed)
OutputTrue
3. Writing
f.write(text) writes exactly the string you give. It adds no new line, so include \n yourself.
write() needs a string: convert numbers with str() or an f-string.
print(..., file=f) writes and adds the new line for you.
f.writelines(list) writes each string; it does not add new lines.
total = 42
with open("out.txt", "w", encoding="utf-8") as f:
f.write(f"Total: {total}\n")
print("Done", file=f)
with open("out.txt", encoding="utf-8") as f:
print(f.read(), end="")
OutputTotal: 42
Done
4. Reading
f.read() gives the whole file as one string.
f.readline() gives the next line.
f.readlines() gives all lines as a list.
for line in f: reads one line at a time, the best choice for big files.
with open("notes.txt", "w", encoding="utf-8") as f:
f.write("cat\ndog\nbird\n")
with open("notes.txt", encoding="utf-8") as f:
for line in f:
print(line.strip())
Outputcat
dog
bird
Remember: Each line ends with an invisible \n. Use line.strip() before comparing or printing it.
5. The file position
A file object remembers where it is. After read(), the position is at the end, so a second read() returns an empty string. seek(0) goes back to the start.
with open("notes.txt", "w", encoding="utf-8") as f:
f.write("hello")
with open("notes.txt", encoding="utf-8") as f:
print(repr(f.read()))
print(repr(f.read()))
f.seek(0)
print(repr(f.read()))
Output'hello'
''
'hello'
6. Handling missing files
import os
try:
with open("ghost.txt", encoding="utf-8") as f:
data = f.read()
except FileNotFoundError:
data = ""
print(repr(data), os.path.exists("ghost.txt"))
Output'' False
Example: Simple CSV: name, age, city = line.strip().split(","). For real CSV files with quoted commas, use the csv module.
7. Saving data with JSON
The json module saves lists and dicts as text and loads them back. dump/load work with files; dumps/loads work with strings.
import json
scores = {"Ana": 92, "Ben": 85}
with open("save.json", "w", encoding="utf-8") as f:
json.dump(scores, f)
with open("save.json", encoding="utf-8") as f:
loaded = json.load(f)
print(loaded["Ana"])
print(json.dumps([1, 2, 3]))
Output92
[1, 2, 3]
8. Good habits
Always use with.
Pass encoding="utf-8" so text in any language reads correctly on every computer.
Never use eval() on file contents; use json.
9. Common misconceptions
Misconception
Correct understanding
"w" mode adds to a file.
"w" erases the file first; "a" adds to the end.
write() adds a new line like print().
write() writes only what you pass; add \n yourself.
You can call f.read() after the with block.
The file is closed there; reading raises ValueError.
A second read() reads the file again.
The position is at the end; use seek(0) first.
write(42) works.
write() needs a string: write(str(42)).
10. Quick revision
"r"
Read mode; the file must exist.
"w"
Write mode; erases the file first.
"a"
Append mode; adds to the end.
with
Closes the file automatically.
read()
Whole file as one string.
for line in f
Reads one line at a time.
seek(0)
Back to the start of the file.
json.dump / json.load
Save / load data as JSON.
11. Test your understanding
Which mode adds to the end of a file?
Show answer
"a" (append).
What is the danger of "w" mode?
Show answer
It erases the existing content as soon as the file opens.
Why use with open(...) as f:?
Show answer
The file is closed automatically, even if an error happens.
What is the best way to read a huge file?
Show answer
for line in f: one line at a time.
Why call line.strip() on lines from a file?
Show answer
Each line ends with a \n character.
What does a second f.read() return?
Show answer
An empty string, because the position is at the end.
Which error comes from opening a missing file for reading?
Show answer
FileNotFoundError.
How do you save a dict to a file?
Show answer
json.dump(data, f)
Key takeaway: Open files with with, choose the right mode (beware "w"), remember write() adds no new line, and use json to save structured data.
Notes written by Velnov. Every code example with an output was run in Python 3 to check that the output shown is exactly what Python prints.
f = open("notes.txt", "r")
text = f.read()
f.close()
A open()
B file()
C read()
D load()
Answer: A β open()
open(path, mode) returns a file object: open("notes.txt", "r") opens for reading. The mode defaults to "r" if omitted.
open()File modes
Q2.easy
What does mode "r" mean in open("data.txt", "r")?
A Read - file must already exist
B Remove the file
C Rename the file
D Read and write
Answer: A β Read - file must already exist
"r" opens for READING only. If the file doesn't exist you get FileNotFoundError. Other modes: "w" write, "a" append, "x" create-new.
File modesFileNotFoundError
Q4.easy
Which mode ADDS to the end of a file without deleting what's there?
with open("log.txt", "a") as f:
f.write("user logged in\n")
A "w"
B "a"
C "r"
D "end"
Answer: B β "a"
"a" = append. Writes always go to the end; existing content is safe. Perfect for log files. The file is created if it doesn't exist.
Append modeLogs
Q5.easy
What is the PREFERRED way to open files, and why?
with open("notes.txt") as f:
text = f.read()
# file is ALREADY closed here
A with open(...) as f: - the file closes automatically, even on errors
B f = open(...) - simpler
C It makes no difference
D global open
Answer: A β with open(...) as f: - the file closes automatically, even on errors
The with statement (context manager) guarantees the file is closed when the block ends - even if an exception occurs inside. No forgotten close(), no leaked file handles.
Modern Python code almost never calls close() manually.
with statementContext managers
Q6.easy
What does f.read() return?
with open("poem.txt") as f:
text = f.read() # one big string
print(len(text))
A The ENTIRE file content as one string
B One line
C A list of lines
D The file size
Answer: A β The ENTIRE file content as one string
read() slurps the whole file into a single string (newlines included). readline() gives one line; readlines() gives a list of all lines.
read()readlines()
Q10.easy
How do you WRITE text to an open file f?
with open("out.txt", "w") as f:
f.write("hello\n")
f.write("world\n")
A f.write("hello")
B f.print("hello")
C write(f, "hello")
D f << "hello"
Answer: A β f.write("hello")
f.write(string) writes exactly the string you give - and returns the number of characters written.
write()
Q13.easy
Opening a missing file in "r" mode raises:
try:
with open("ghost.txt") as f:
data = f.read()
except FileNotFoundError:
data = ""
A FileNotFoundError
B ValueError
C KeyError
D Nothing - it creates the file
Answer: A β FileNotFoundError
Read mode requires the file to exist. Write ("w") and append ("a") modes CREATE missing files instead.
FileNotFoundErrortry/except
Q24.easy
How do you count the lines in a file?
with open("data.txt") as f:
count = sum(1 for _ in f)
print(count, "lines")
A sum(1 for line in f) or len(f.readlines())
B f.count_lines()
C f.length
D count(f)
Answer: A β sum(1 for line in f) or len(f.readlines())
Iterate and count: sum(1 for line in f) is memory-friendly; len(f.readlines()) is fine for small files. There's no built-in line counter.
IterationGenerator expressions
Q26.easy
Which snippet appends one log entry safely?
A with open("app.log", "a") as f:\n f.write("login ok\n")
B with open("app.log", "w") as f:\n f.write("login ok\n")
C open("app.log").write("login ok")
D append("app.log", "login ok")
Answer: A β with open("app.log", "a") as f:\n f.write("login ok\n")
Mode "a" preserves old entries; with guarantees the file closes. Option B wipes the log each time; option C never closes and uses read mode.
Append modewith statement
Q29.easy
After 'with open(...) as f:' ends, is the file open or closed?
with open("a.txt") as f:
pass
print(f.closed) # True
A Closed - automatically, always
B Open until program exit
C Open until garbage collection
D Depends on the mode
Answer: A β Closed - automatically, always
That's the whole point of with: the file is closed the instant the block exits - normally or via an exception. f.closed is True afterwards.
Context managers
Medium questions (14)
Q3.medium
What is the DANGER of mode "w"?
open("log.txt", "w") # content GONE
open("log.txt", "a") # content kept, writes go to the end
A It's slower
B It ERASES the file's existing content the moment it opens
C It can't create new files
D It locks the file forever
Answer: B β It ERASES the file's existing content the moment it opens
"w" truncates: opening an existing file in "w" instantly wipes it - even if you never write anything. Use "a" (append) to keep existing content and add to the end.
Real data has been lost to this. Double-check your mode!
Write modeAppend mode
Q7.medium
What is the difference between readline() and readlines()?
with open("data.csv") as f:
header = f.readline() # first line only
rest = f.readlines() # remaining lines as a list
A readline() returns the NEXT single line; readlines() returns ALL lines as a list
B They're identical
C readlines() reads one line
D readline() returns a list
Answer: A β readline() returns the NEXT single line; readlines() returns ALL lines as a list
readline() advances one line per call - good for reading just the header. readlines() loads every line into a list at once - convenient, but memory-heavy for huge files.
readline()readlines()
Q8.medium
What is the BEST way to process a large file line by line?
with open("big.log") as f:
for line in f:
if "ERROR" in line:
print(line.strip())
A for line in f: - iterate the file object directly
B f.read().split() always
C readlines() then loop
D while f.next():
Answer: A β for line in f: - iterate the file object directly
A file object is iterable - looping it reads ONE line at a time, so even gigabyte files use tiny memory. readlines() would load everything at once.
IterationMemory efficiency
Q9.medium
Why call line.strip() when reading lines from a file?
for line in f:
name = line.strip()
if name == "cat": # now matches
print("found")
A Each line ends with an invisible \n newline - strip() removes it
B To remove all spaces inside the line
C Files require it
D To convert to lowercase
Answer: A β Each line ends with an invisible \n newline - strip() removes it
Lines keep their trailing newline character, so print(line) double-spaces and comparisons fail ('cat\n' != 'cat'). strip() (or rstrip()) cleans it off.
strip()Newlines
Q11.medium
What's the catch with f.write() compared to print()?
f.write("a")
f.write("b") # file contains: ab
f.write("c\n") # add \n yourself
print("d", file=f) # or use print
A write() does NOT add a newline automatically - you must include \n yourself
B write() adds two newlines
C write() can't write strings
D No difference
Answer: A β write() does NOT add a newline automatically - you must include \n yourself
print() appends \n for you; write() writes ONLY what you pass. Forgetting \n glues all your lines into one. Alternative: print("text", file=f) adds the newline.
write()Newlines
Q12.medium
What happens with f.write(42)?
total = 42
f.write(str(total) + "\n")
f.write(f"Total: {total}\n") # cleaner
A Writes 42
B TypeError - write() needs a string, so convert: f.write(str(42))
C Writes '42' automatically
D Writes binary
Answer: B β TypeError - write() needs a string, so convert: f.write(str(42))
write() only accepts strings (in text mode). Numbers must be converted first: str(42) or an f-string f"{42}\n".
TypeErrorstr()
Q15.medium
When do you need mode "rb" or "wb"?
with open("photo.jpg", "rb") as src:
data = src.read() # bytes
with open("copy.jpg", "wb") as dst:
dst.write(data)
A For BINARY files - images, audio, zip files - where data is bytes, not text
B For very big text files
C For read-backwards mode
D Never - text mode handles everything
Answer: A β For BINARY files - images, audio, zip files - where data is bytes, not text
The b suffix switches to binary mode: read() returns bytes instead of str, and no newline translation happens. Copying an image in text mode corrupts it.
Binary modebytes
Q16.medium
What happens when you read from a file AFTER closing it?
with open("a.txt") as f:
data = f.read() # inside: OK
# f.read() # outside: ValueError!
A Returns empty string
B ValueError: I/O operation on closed file
C Reopens automatically
D Returns None
Answer: B β ValueError: I/O operation on closed file
A closed file object refuses all operations with ValueError. A common bug: doing f.read() OUTSIDE the with block - the file is already closed there.
with statementValueError
Q19.medium
A simple way to parse the CSV line "Ana,21,Delhi"?
with open("students.csv") as f:
for line in f:
name, age, city = line.strip().split(",")
print(name, age)
A line.strip().split(",") -> ['Ana', '21', 'Delhi']
B line.parse()
C line.csv()
D int(line)
Answer: A β line.strip().split(",") -> ['Ana', '21', 'Delhi']
split(",") cuts a comma-separated line into fields. For real CSV files with quoted commas, use the csv module - but split() handles simple data fine.
split()csv module
Q20.medium
Which module converts Python dicts to/from the JSON text format?
import json
data = {"name": "Ana", "score": 92}
with open("save.json", "w") as f:
json.dump(data, f)
with open("save.json") as f:
loaded = json.load(f)
print(loaded["score"]) # 92
A json
B dict
C text
D xml
Answer: A β json
The built-in json module: json.dump(data, f) writes a dict as JSON to a file; json.load(f) reads it back. The universal format for configs and APIs.
json moduleSerialization
Q22.medium
How do you check whether a file exists BEFORE opening it?
import os
if os.path.exists("save.json"):
load_game()
else:
new_game()
A os.path.exists("data.txt") (or pathlib's Path("data.txt").exists())
B open.exists("data.txt")
C file.check("data.txt")
D exists "data.txt"
Answer: A β os.path.exists("data.txt") (or pathlib's Path("data.txt").exists())
os.path.exists() returns True/False. (The EAFP alternative: just open it and catch FileNotFoundError - equally Pythonic.)
os.pathpathlibEAFP
Q23.medium
Why pass encoding="utf-8" to open()?
with open("notes.txt", encoding="utf-8") as f:
text = f.read() # handles any language
A So text with any language/emoji reads and writes correctly on every OS
B It compresses the file
C It's required for numbers
D It makes files read-only
Answer: A β So text with any language/emoji reads and writes correctly on every OS
Without it, Python uses a platform-dependent default (often cp1252 on Windows) - files with Γ±, δΈζ or emoji can crash or garble. Explicit utf-8 makes your code portable.
Good habit: always specify encoding for text files.
EncodingUnicode
Q25.medium
What does writelines() do - and what does it NOT do?
lines = ["one\n", "two\n", "three\n"]
with open("out.txt", "w") as f:
f.writelines(lines)
A Writes each string from a list; it does NOT add newlines between them
B Writes lines and adds newlines automatically
C Reads lines
D Writes one line only
Answer: A β Writes each string from a list; it does NOT add newlines between them
Despite the name, writelines(list) just concatenates the strings - no separators added. Include \n in each string yourself.
writelines()Newlines
Q28.medium
What does mode "r+" allow?
A Both reading AND writing, without erasing the file first
B Reading twice as fast
C Reading with automatic retry
D Read-only, but raises no errors
Answer: A β Both reading AND writing, without erasing the file first
"r+" opens an EXISTING file for read and write - the cursor starts at the beginning, and writes overwrite bytes in place. ("w+" also reads+writes but truncates first.)
File modesr+ vs w+
Hard questions (6)
Q14.hard
What does mode "x" do?
try:
with open("config.ini", "x") as f:
f.write("[defaults]\n")
except FileExistsError:
print("config already exists - not touching it")
A Creates a NEW file - fails with FileExistsError if it already exists
B Extracts the file
C Executes the file
D Deletes the file
Answer: A β Creates a NEW file - fails with FileExistsError if it already exists
"x" is exclusive creation - a safe 'create only if new'. Unlike "w" it can never accidentally wipe an existing file.
Exclusive modeFileExistsError
Q17.hard
Why does the SECOND read() return an empty string?
data1 = f.read()
data2 = f.read()
data1 = f.read() # everything; cursor at end
data2 = f.read() # '' - nothing left
f.seek(0) # rewind
data3 = f.read() # everything again
A The file position is at the END after the first read - there's nothing left to read
B Files can only be read once ever
C It's a bug in Python
D The file gets deleted after reading
Answer: A β The file position is at the END after the first read - there's nothing left to read
A file object keeps a position cursor. read() moves it to the end; the next read() starts there and finds nothing. f.seek(0) rewinds to the beginning to read again.
File positionseek()
Q18.hard
What does f.seek(0) do?
A Moves the read/write position back to the START of the file
B Deletes the first byte
C Searches for the number 0
D Closes the file
Answer: A β Moves the read/write position back to the START of the file
seek(position) jumps the file cursor to that byte offset - seek(0) rewinds to the beginning. f.tell() reports the current position.
seek()tell()
Q21.hard
What is the difference between json.dump() and json.dumps()?
import json
text = json.dumps({"a": 1}) # '{"a": 1}' - a string
data = json.loads(text) # back to a dict
A dump() writes to a FILE; dumps() returns a STRING (s = string)
B dumps() is the plural version for lists
C dump() deletes the data after
D No difference
Answer: A β dump() writes to a FILE; dumps() returns a STRING (s = string)
The trailing s means 'string': dumps(data) gives you the JSON text to use however you like; dump(data, f) writes it straight into a file. Same pair for reading: loads(text) vs load(f).
json moduledumps vs dump
Q27.hard
Copy a text file. Fill the blank:
with open("a.txt") as src, ______ as dst:
dst.write(src.read())
with open("a.txt") as src, open("b.txt", "w") as dst:
dst.write(src.read())
A open("b.txt", "w")
B open("b.txt", "r")
C copy("b.txt")
D open("b.txt")
Answer: A β open("b.txt", "w")
One with statement can manage MULTIPLE files (comma-separated). The destination needs write mode; options B/D open read-only and writing would fail.
Multiple context managersCopying
Q30.hard
You need to save a Python LIST so another run of your program can reload it. Best simple approach?
import json
scores = [90, 85, 77]
with open("scores.json", "w") as f:
json.dump(scores, f)
with open("scores.json") as f:
scores = json.load(f)
A json.dump() it to a file, json.load() to restore
B write(str(list)) and eval() it back
C Print it and copy-paste later
D Lists can't be saved
Answer: A β json.dump() it to a file, json.load() to restore
JSON handles lists, dicts, strings, numbers and bools - safe and readable. eval() on file content is a security hole (it executes anything). For arbitrary Python objects, the pickle module exists - but JSON is the safe default.