Reading & Writing Files

Programs need to save data and read it back: settings, logs, reports, datasets. Python's built-in open() handles text and binary files, and the with statement makes sure files are always closed properly.

Writing a file

PY write.py
with open("notes.txt", "w", encoding="utf-8") as f:
    f.write("First line\n")
    f.write("Second line\n")
    print("Third line", file=f)

print("saved")
Output
saved

open(path, mode) returns a file object. Mode "w" creates the file, or overwrites it if it exists. write() doesn't add newlines for you; print(..., file=f) does. The with block closes the file automatically when it ends — even if an error occurs.

Always pass encoding="utf-8" for text files. Without it, Python uses the system's default encoding, which differs between Windows and other systems and can garble accented characters and emoji.

Reading a file

PY read.py
with open("notes.txt", "w", encoding="utf-8") as f:
    f.write("apples\nbananas\ncherries\n")

with open("notes.txt", encoding="utf-8") as f:
    content = f.read()
print(repr(content))

with open("notes.txt", encoding="utf-8") as f:
    for line in f:
        print(line.rstrip("\n").upper())

with open("notes.txt", encoding="utf-8") as f:
    lines = f.read().splitlines()
print(lines)
Output
'apples\nbananas\ncherries\n'
APPLES
BANANAS
CHERRIES
['apples', 'bananas', 'cherries']
  • f.read() returns the whole file as one string.
  • Looping over the file gives one line at a time, including its trailing \n. This is memory-efficient even for huge files.
  • f.read().splitlines() gives a list of lines without newline characters.

File modes

ModeMeaning
"r"Read (default). Error if the file doesn't exist
"w"Write. Creates or truncates the file
"a"Append to the end. Creates the file if needed
"x"Create; error if the file already exists — safe against overwriting
"b"Binary, combined with the above: "rb", "wb"
"+"Read and write: "r+"

Appending

PY append.py
from datetime import datetime

def log(message):
    stamp = datetime(2026, 10, 6, 9, 30).strftime("%H:%M")
    with open("app.log", "a", encoding="utf-8") as f:
        f.write(f"{stamp} {message}\n")

open("app.log", "w").close()
log("started")
log("processed 42 rows")

with open("app.log", encoding="utf-8") as f:
    print(f.read(), end="")
Output
09:30 started
09:30 processed 42 rows

Handling missing files

PY missing.py
def read_settings(path):
    try:
        with open(path, encoding="utf-8") as f:
            return f.read()
    except FileNotFoundError:
        print(f"{path} not found, using defaults")
        return ""

read_settings("does-not-exist.ini")
Output
does-not-exist.ini not found, using defaults

Processing a file line by line

PY process.py
data = """name,score
Ana,91
Ben,78
Cleo,85
"""
with open("scores.csv", "w", encoding="utf-8") as f:
    f.write(data)

total = count = 0
with open("scores.csv", encoding="utf-8") as f:
    next(f)
    for line in f:
        name, score = line.strip().split(",")
        total += int(score)
        count += 1

print(f"{count} students, average {total / count:.1f}")
Output
3 students, average 84.7

next(f) skips the header row. For real CSV files with quoted commas, use the csv module (lesson 45).

Binary files

PY binary.py
data = bytes([0x89, 0x50, 0x4E, 0x47])

with open("header.bin", "wb") as f:
    f.write(data)

with open("header.bin", "rb") as f:
    raw = f.read()

print(raw, raw[1:].decode("ascii"), len(raw))
Output
b'\x89PNG' PNG 4

Binary mode reads and writes bytes instead of str — use it for images, PDFs, archives and any non-text format. Never pass encoding in binary mode.

Several files at once

PY two_files.py
with open("notes.txt", "w", encoding="utf-8") as f:
    f.write("b\na\nc\n")

with open("notes.txt", encoding="utf-8") as src, open("sorted.txt", "w", encoding="utf-8") as dst:
    dst.writelines(sorted(src))

with open("sorted.txt", encoding="utf-8") as f:
    print(f.read().split())
Output
['a', 'b', 'c']

Try it yourself

The editor runs Python in your browser with a temporary, in-memory file system, so you can create and read files freely:

Try it yourself
Console output