Reading/Writing Files & Context Managers
You'll learn to
- -Open a file for reading or writing with `open()` and the correct mode
- -Explain why `with open(...) as f:` is the correct pattern instead of manual open/close
- -Read a file's contents line by line or all at once
Every program you have written so far has lived and died in memory. Close the program, and everything is gone. Reading and writing files is how a program persists data across runs. This chapter also introduces context managers, a pattern you will recognize again the moment you meet database connections or network sockets later.
open() and File Modes
open(path, mode) returns a file object. The mode controls what you can do with it: "r" for reading (the default), "w" for writing (creates the file if missing, and overwrites it if it already exists), and "a" for appending to the end of an existing file.
f = open("notes.txt", "w")
f.write("first line\n")
f.write("second line\n")
f.close() # easy to forget!
f = open("notes.txt", "r")
contents = f.read()
f.close()
print(contents)
# first line
# second lineWhy with open(...) as f: Is the Correct Pattern
Manually calling .close() has a real problem: if an exception is raised between open() and .close(), the .close() call never runs, and the file is left open, which can mean data never gets flushed to disk, or the file stays locked for other programs. A with block is Python's context manager syntax. It guarantees .close() runs automatically when the block exits, whether it exits normally or via an exception.
with open("notes.txt", "w") as f:
f.write("first line\n")
f.write("second line\n")
# f.close() is called automatically here, even if an exception had occurred above
with open("notes.txt", "r") as f:
contents = f.read()
print(contents)Always prefer with open(...) as f: over manual open()/.close() pairs. It is shorter, and it is correct in the presence of exceptions in a way that manual closing is not.
Reading Line by Line
A file object is itself iterable line by line, which is memory-efficient for large files. You never have to load the whole file into memory at once the way .read() does.
with open("notes.txt", "r") as f:
for line in f:
print(line.strip()) # .strip() removes the trailing newline
with open("notes.txt", "r") as f:
lines = f.readlines() # or: get every line at once, as a list of strings
print(lines) # ['first line\n', 'second line\n']- -"r" reads (the file must already exist). "w" writes, overwriting any existing content. "a" appends to the end.
- -with open(...) as f: guarantees the file is closed even if an exception occurs inside the block. Always prefer it.
- -f.read() loads the whole file as one string. Iterating over f (or calling f.readlines()) gives it to you line by line.
Interview Signal is part of Pro
See a real weak answer next to a real strong one for this exact topic.
Quiz is part of Pro
Test what you just read with a short quiz, and bank the XP.
Discussion0
Join the Discussion
Sign in to leave comments, reply to others, or like insights.
No comments yet. Be the first to start the thread!