Reading and Writing Files in Python
Python reads and writes files with the built-in open() function, which returns a file object. Open the file in a with statement, so Python closes it when the block ends, and pass a mode such as "w" to write or "a" to append.
Key facts
open("notes.txt")opens a file for reading, andopen("notes.txt", "w")creates it or empties it for writing.- A
withstatement closes the file when its block ends, even if an error happens inside it. f.read()returns the whole file as one string, andfor line in f:reads it one line at a time.f.write()adds no line break, so each line needs its own\n.- Opening a missing file for reading raises
FileNotFoundError.
How do I open a file in Python?
Call open() inside a with statement and pass it the file name, a mode and an encoding. The with block gives you the file object as f and closes the file when the block ends.
with open("notes.txt", "w", encoding="utf-8") as f:
f.write("Buy milk\n")
f.write("Call Sam\n")
with open("notes.txt", encoding="utf-8") as f:
print(f.read(), end="")Buy milk Call Sam
The first block opens notes.txt in write mode, "w", which creates the file, and writes two lines. write() adds no line break, so each line ends with \n.
The second block opens the file in the default read mode and prints all of it. end="" stops print() from adding a line break after the file's last one, as in the input and output lesson.
An encoding is the rule that turns text into bytes, the numbers from 0 to 255 that a file stores. UTF-8 can store any character, which is why every example passes encoding="utf-8".
Closing matters because written text may not reach the disk until the file is closed. The with statement closes it even when an error stops the block, like the finally clause in the errors and exceptions lesson.
Each example that needs a file writes it first, so the examples work in any order. In the runner, files stay in memory until the page reloads or Python restarts, which happens when you press Stop or a program runs too long.
How do I read a file in Python?
Open the file and call read() to get the whole file as one string. readline() returns the next line, and readlines() returns every line in a list.
with open("colors.txt", "w", encoding="utf-8") as f:
f.write("red\ngreen\nblue\n")
with open("colors.txt", encoding="utf-8") as f:
lines = f.readlines()
print(lines)
print(len(lines))['red\n', 'green\n', 'blue\n'] 3
Each string in the list keeps its \n, the line break at the end of the line.
| Code | Gives you | Use it when |
|---|---|---|
f.read() | The whole file as one string | The file is small and you want all of it |
f.readline() | The next line, or an empty string at the end | You need one line, such as a header |
f.readlines() | A list with one string per line | You want the lines as a list |
for line in f: | One line per pass of the loop | The file is large, or you handle each line on its own |
How do I read a file line by line in Python?
Loop over the file object with for line in f:. Each pass gets the next line, and Python reads the file as the loop goes instead of loading it all at once.
with open("colors.txt", "w", encoding="utf-8") as f:
f.write("red\ngreen\nblue\n")
with open("colors.txt", encoding="utf-8") as f:
for number, line in enumerate(f, start=1):
print(number, line.strip())1 red 2 green 3 blue
strip() removes the \n and any spaces at either end of the line, and rstrip("\n") removes only the line break. Without either, a blank line would follow every line, because the line already ends in a line break and print() adds one more.
enumerate() numbers the lines, as in the for loops lesson.
How do I write to a file in Python?
Open the file in "w" mode and call write() with a string. The moment open() runs, write mode creates the file if it doesn't exist or empties it if it does.
with open("todo.txt", "w", encoding="utf-8") as f:
f.write("Old task\n")
with open("todo.txt", "w", encoding="utf-8") as f:
count = f.write("New task\n")
print(count)
with open("todo.txt", encoding="utf-8") as f:
print(f.read(), end="")9 New task
The second open() emptied the file, removing Old task before anything was written. write() returns the number of characters it wrote, 9 here, with the \n counted as one.
write() accepts strings only, so turn a number into text first, as in f.write(str(42)). To write a list, loop over it and write each item followed by \n.
How do I append to a file in Python?
Open the file in "a" mode. Append mode keeps what is already in the file and adds the text from each write() call to the end, which suits logs and running lists.
with open("log.txt", "w", encoding="utf-8") as f:
f.write("Started\n")
with open("log.txt", "a", encoding="utf-8") as f:
f.write("Saved file\n")
f.write("Stopped\n")
with open("log.txt", encoding="utf-8") as f:
print(f.read(), end="")Started Saved file Stopped
Append mode also creates the file when it is missing. Appended text starts exactly where the file ends, so if the last line has no \n, the new text joins onto that line.
What do the file modes mean in Python?
The mode is the second argument to open(), and it decides what you can do with the file. Leave it out and Python opens the file for reading, the same as "r".
| Mode | Purpose | If the file exists | If the file is missing |
|---|---|---|---|
"r" | Read (the default) | Reads from the start | FileNotFoundError |
"w" | Write | Empties it first | Creates it |
"a" | Append | Keeps it and writes at the end | Creates it |
"x" | Create | FileExistsError | Creates it |
"r+" | Read and write | Keeps it, and writing overwrites text instead of inserting it | FileNotFoundError |
"w+" | Write and read | Empties it first | Creates it |
"a+" | Append and read | Keeps it and writes at the end | Creates it |
Add b for binary files such as images, as in "rb" or "wb". Binary mode reads and writes bytes instead of text, so it takes no encoding.
with open("report.txt", "w", encoding="utf-8") as f:
f.write("Draft 1\n")
try:
with open("report.txt", "x", encoding="utf-8") as f:
f.write("Draft 2\n")
except FileExistsError:
print("report.txt already exists")report.txt already exists
Use "x" when replacing a file by accident would lose data. It refuses to open a file that already exists, where "w" would empty it.
What happens when you open a file that doesn't exist in Python?
Opening a missing file for reading raises FileNotFoundError. Catch it with try and except when the file might not be there yet.
try:
with open("settings.txt", encoding="utf-8") as f:
print(f.read())
except FileNotFoundError:
print("No saved settings yet")No saved settings yet
Without the try statement, the program would stop with a FileNotFoundError whose message starts with [Errno 2] No such file or directory. The runner shows [Errno 44] instead, because its browser build of Python numbers system errors differently.
A name without a folder, such as settings.txt, means a file in the current working directory. When you start the program from a terminal, that's the terminal's folder, which isn't always the script's folder. After import os, print(os.getcwd()) shows it.
Why should I pass encoding="utf-8" to open()?
Passing encoding="utf-8" makes Python use the same encoding for the file on every computer. Without it, Python 3.14 and earlier use the system's default encoding, which is usually UTF-8 on macOS and Linux.
On Windows the default is often cp1252, an older encoding for Western European languages. Reading a UTF-8 file with it garbles the text, so café shows up as café, and some characters stop the read with a UnicodeDecodeError.
Writing a character the default encoding can't store, such as an emoji, stops with a UnicodeEncodeError. The runner always uses UTF-8, so these errors show up only on your own computer.
Python 3.15 made UTF-8 the default for open(). Passing it yourself keeps a program correct on 3.14 and earlier, and it tells anyone reading the code which encoding the file uses.
Common mistakes with files in Python
The first of these four file handling mistakes loses data silently, and the others stop the program.
- Opening a file in "w" mode to add to it. Write mode empties the file the moment it opens, before you write anything. Use
"a"to add to the end. - FileNotFoundError: [Errno 2] No such file or directory: 'notes.txt'. This often means the program started in a different folder from the file. Check the name, run
print(os.getcwd())afterimport os, or give the full path. - TypeError: write() argument must be str, not int.
f.write(42)passed a number, andwrite()takes only strings. Turn it into text first, as inf.write(str(42)). - ValueError: I/O operation on closed file. The file is closed once its
withblock ends, sof.read()after the block fails. Read inside the block and keep the result in a variable.
The program below writes a number. Change 42 to "42" and run it again.
with open("score.txt", "w", encoding="utf-8") as f:
f.write(42)
with open("score.txt", encoding="utf-8") as f:
print(f.read())Traceback (most recent call last):
File "main.py", line 2, in <module>
f.write(42)
~~~~~~~^^^^
TypeError: write() argument must be str, not intExercise
Add a line break after each name when writing, and keep the "w" mode, so names.txt holds one name per line and the program prints Ada, Grace and Linus on three lines. The starter prints AdaGraceLinus, because write() adds no line break.
names = ["Ada", "Grace", "Linus"]
with open("names.txt", "w", encoding="utf-8") as f:
for name in names:
f.write(name)
with open("names.txt", encoding="utf-8") as f:
for line in f:
print(line.strip())
Ada Grace Linus
Show the solution
names = ["Ada", "Grace", "Linus"]
with open("names.txt", "w", encoding="utf-8") as f:
for name in names:
f.write(name + "\n")
with open("names.txt", encoding="utf-8") as f:
for line in f:
print(line.strip())
Quiz
This quiz has 5 questions. Pick an answer to see why it is right or wrong.
-
1What does this program print?
with open("a.txt", "w", encoding="utf-8") as f: f.write("one") with open("a.txt", "w", encoding="utf-8") as f: f.write("two") with open("a.txt", encoding="utf-8") as f: print(f.read())Each open() in "w" mode empties the file first, so the second block removed the text "one" before it wrote "two". Append mode, "a", would have kept both and printed onetwo, because write() adds no line break.
-
2Which mode adds text to the end of a file without deleting what is already there?
"a" keeps the file and writes after its last character. "w" empties the file first, "r" only reads, and "x" refuses to open a file that exists.
-
3What does this program print?
with open("b.txt", "w", encoding="utf-8") as f: f.write("x\ny\n") with open("b.txt", encoding="utf-8") as f: print(f.readlines())readlines() returns a list with one string per line, and each string keeps its line break, shown as \n. The file ends right after the second line break, so there is no empty third item.
-
4What does a with statement do with a file opened in it?
A with statement closes the file when the block finishes, even after an error, but it doesn't catch the error, which still stops the program. The file is read only when your code asks for it, with read() or a for loop.
-
5What happens when open("data.txt") runs and data.txt does not exist?
Without a mode, open() reads, and reading needs an existing file, so Python raises FileNotFoundError. Modes like "w", "a" and "x" create a missing file.























