Reading and Writing Files in Python
Learn to read and write text files in Python: open files safely with the with statement, use read, readlines and write, append data, handle paths and avoid common errors. Runnable code, a worked program and a quiz.
Key takeaways
- open(path, mode) connects your program to a file; the mode chooses read, write or append
- The with open(...) as f: block opens a file and closes it automatically when you are done
- Reading: read() gets the whole file, readlines() gives a list of lines, or loop over the file directly
- Writing with 'w' replaces the whole file; 'a' adds to the end without erasing what is there
- write() does not add newlines for you, so include \n yourself when you want separate lines
Why programs need files
Everything a program stores in variables vanishes the moment it stops running. Close the window and your high score, your saved notes, your to-do list โ all gone. To keep information between runs, you have to save it somewhere permanent: a file on disk. Files are also how programs share data with each other, with you, and with the wider world.
In this lesson you'll learn to read text out of files and write text into them. If you're comfortable running a program and using variables, you're ready. Everything here works in a plain .py file or in any Python interpreter.
Opening a file
You connect your program to a file with the built-in open() function. It needs the filename and a mode that says what you intend to do:
f = open("notes.txt", "r")
content = f.read()
print(content)
f.close()
The three most common modes are:
| Mode | Meaning | If the file is missing | Effect on existing content |
|---|---|---|---|
"r" | read | error | unchanged |
"w" | write | creates it | erased first |
"a" | append | creates it | kept; new text added at end |
Notice the last line, f.close(). An open file is a limited resource, and forgetting to close it can lose data or lock the file. The trouble is, if an error happens before close(), it never runs. There's a much safer pattern.
The with statement: the safe way
Almost all real Python file code uses a with block. It opens the file, gives it a name, and closes it automatically when the block ends โ even if something goes wrong inside:
with open("notes.txt", "r") as f:
content = f.read()
print(content)
# the file is now closed automatically
Read this as: "open notes.txt for reading, call it f, and run the indented block." When the indented code finishes, Python closes f for you. Use this form from now on; it's cleaner and far less error-prone than calling close() by hand.
Three ways to read
Once a file is open in read mode, you have choices about how to pull text out of it.
read() returns the entire file as one big string:
with open("poem.txt", "r") as f:
whole = f.read()
print(whole)
readlines() returns a list, one string per line (each still ending in \n):
with open("poem.txt", "r") as f:
lines = f.readlines()
print(len(lines), "lines")
print(lines[0])
Looping directly over the file is the most memory-friendly way, because it reads one line at a time. This is the idiom you'll use most:
with open("poem.txt", "r") as f:
for line in f:
print(line.strip())
line.strip() removes the trailing newline (and any stray spaces), so print doesn't add a second blank line. If you skip .strip(), you'll see double-spaced output, because print adds its own newline on top of the one already in the line.
Writing to a file
Opening in "w" mode lets you write. Be careful: it erases the file first. The write() method adds exactly the text you give it โ no automatic newlines:
with open("greeting.txt", "w") as f:
f.write("Hello!\n")
f.write("This is line two.\n")
Without the \n characters, both pieces of text would land on the same line. If you have a list of strings to save, writelines() writes them all in order (again, you supply the newlines):
items = ["apple\n", "banana\n", "cherry\n"]
with open("fruit.txt", "w") as f:
f.writelines(items)
Appending instead of overwriting
When you want to add to a file without destroying what's already there โ a log, a journal, a running high-score list โ use "a":
with open("log.txt", "a") as f:
f.write("Program started\n")
Run that program five times and you'll have five lines, not one. That's the whole difference between "w" (replace) and "a" (add).
Handling a missing file gracefully
Reading a file that doesn't exist raises a FileNotFoundError and stops your program. You can catch it and respond calmly instead of crashing:
try:
with open("settings.txt", "r") as f:
print(f.read())
except FileNotFoundError:
print("No settings file yet โ using defaults.")
This try / except pattern is the polite way to deal with files that may or may not be there.
Worked example: a simple notes keeper
Let's combine reading, appending, and graceful error-handling into one complete program. It lets you add notes, then shows everything you've ever saved.
NOTES_FILE = "my_notes.txt"
def add_note(text):
"""Append one note (with a newline) to the notes file."""
with open(NOTES_FILE, "a") as f:
f.write(text + "\n")
def show_notes():
"""Print every saved note, numbered. Handle a missing file."""
try:
with open(NOTES_FILE, "r") as f:
lines = f.readlines()
except FileNotFoundError:
print("You have no notes yet.")
return
if not lines:
print("You have no notes yet.")
return
print("Your notes:")
for number, line in enumerate(lines, start=1):
print(f"{number}. {line.strip()}")
# Try the program
add_note("Buy milk")
add_note("Finish Python homework")
add_note("Call Grandma")
show_notes()
Walking through it:
NOTES_FILEis a constant holding the filename in one place, so it's easy to change later.add_noteopens in append mode and writes the text plus a\n, so each note sits on its own line and earlier notes are kept.show_notesreads all the lines into a list. If the file is missing, theexceptblock prints a friendly message andreturns early instead of crashing.enumerate(lines, start=1)gives both a counter and each line, so we can print numbered notes..strip()removes the stored newline so the numbering looks tidy.
Run it once and three notes appear. Run it again and you'll see six โ proof that append mode keeps your data between runs.
Try it yourself
Turn the notes keeper into a tiny menu-driven app:
- Add a loop that asks the user: type
addto write a note,listto show all notes, orquitto stop. Use input and output to read their choice. - When they choose
add, ask for the note text and calladd_note. - When they choose
list, callshow_notes. - As a stretch, add a
clearoption that opens the file in"w"mode and writes nothing โ wiping it clean. Ask "Are you sure?" before you do, since"w"is unforgiving.
Once your data lives in files, the next step is organising it into rows and columns โ see working with CSV data in Python to store structured records instead of plain lines.
Quick quiz
Test yourself and earn XP
Which file mode opens a file for reading?
"r" means read. "w" opens for writing (erasing the file first) and "a" appends to the end.
Why is the with open(...) as f: form recommended?
The with block guarantees the file is closed when the block ends, so you never forget to call close().
What does mode "w" do to a file that already contains text?
Opening in "w" truncates the file to empty before writing, so any old content is lost.
What does this print if scores.txt contains the line `42\n`? ``` with open("scores.txt") as f: line = f.readline() print(line.strip()) ```
readline() returns "42\n" and .strip() removes the trailing newline, leaving "42".
Does write() automatically add a newline after the text?
write() writes exactly the characters you give it. Include \n in your string to start a new line.
FAQ
Both let you write to a file, but "w" (write) empties the file first, so it replaces everything. "a" (append) keeps the existing content and adds your new text at the end. Use "w" to create or overwrite a fresh file, and "a" to keep adding records like a log or a high-score list.
Python raises a FileNotFoundError and your program stops. You can prevent the crash by checking with os.path.exists() first, or by wrapping the open call in a try / except FileNotFoundError block so you can show a friendly message instead.
Keep exploring
More in Coding