Learn

Short lessons with real code you can edit and run on the page.

Reading and Writing Files in Python

Lesson 30 Python 3.14 Runs in your browser
In short

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, and open("notes.txt", "w") creates it or empties it for writing.
  • A with statement closes the file when its block ends, even if an error happens inside it.
  • f.read() returns the whole file as one string, and for 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.

Python
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="")
Output
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.

Python
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))
Output
['red\n', 'green\n', 'blue\n']
3

Each string in the list keeps its \n, the line break at the end of the line.

Ways to read a file in Python
CodeGives youUse it when
f.read()The whole file as one stringThe file is small and you want all of it
f.readline()The next line, or an empty string at the endYou need one line, such as a header
f.readlines()A list with one string per lineYou want the lines as a list
for line in f:One line per pass of the loopThe 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.

Python
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())
Output
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.

Python
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="")
Output
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.

Python
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="")
Output
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".

File modes for open() in Python
ModePurposeIf the file existsIf the file is missing
"r"Read (the default)Reads from the startFileNotFoundError
"w"WriteEmpties it firstCreates it
"a"AppendKeeps it and writes at the endCreates it
"x"CreateFileExistsErrorCreates it
"r+"Read and writeKeeps it, and writing overwrites text instead of inserting itFileNotFoundError
"w+"Write and readEmpties it firstCreates it
"a+"Append and readKeeps it and writes at the endCreates 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.

Python
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")
Output
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.

Python
try:
    with open("settings.txt", encoding="utf-8") as f:
        print(f.read())
except FileNotFoundError:
    print("No saved settings yet")
Output
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()) after import os, or give the full path.
  • TypeError: write() argument must be str, not int. f.write(42) passed a number, and write() takes only strings. Turn it into text first, as in f.write(str(42)).
  • ValueError: I/O operation on closed file. The file is closed once its with block ends, so f.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.

Python
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())
Output
Traceback (most recent call last):
  File "main.py", line 2, in <module>
    f.write(42)
    ~~~~~~~^^^^
TypeError: write() argument must be str, not int

Exercise

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.

Python
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())
Output
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.

  1. 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())
  2. 2Which mode adds text to the end of a file without deleting what is already there?

  3. 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())
  4. 4What does a with statement do with a file opened in it?

  5. 5What happens when open("data.txt") runs and data.txt does not exist?

Frequently asked questions

How do I create a new text file in Python?
Opening a file in 'w' mode creates it when it doesn't exist, as in open('notes.txt', 'w', encoding='utf-8'). If the file might already be there, use 'x' mode instead, which raises FileExistsError rather than emptying the file.
Do I need to close a file in Python?
Yes, and a with statement does it for you when its block ends. Without a with statement, call f.close() when you finish, because written text may not reach the disk until the file is closed.
What is the difference between 'w' and 'a' mode in Python?
'w' mode empties the file as soon as it opens and writes from the start. 'a' mode keeps the file's text and adds everything to the end, and both modes create the file if it is missing.
How do I check if a file exists in Python?
Import os and call os.path.isfile('notes.txt'), which returns True only when that file exists. If you plan to open the file anyway, open it inside try and catch FileNotFoundError, because the file can vanish between an isfile() check and open().
How do I open a file in another folder in Python?
Pass the file's path to open() instead of a bare name. Use data/notes.txt for a folder inside the current one, or a full path such as C:/Users/Ada/notes.txt. Forward slashes work on Windows too and avoid the escape problems that backslashes cause in ordinary strings.
Why does Python show strange characters like é when it reads my file?
The file was written in one encoding and read in another, usually UTF-8 text read as cp1252 on Windows. Pass encoding='utf-8' to open() both when you write the file and when you read it.
How do I delete a file in Python?
Import os and call os.remove('notes.txt'). It deletes the file for good, without the recycle bin, and raises FileNotFoundError if the file isn't there.