Learn Python / Reading and Writing Files

Reading and Writing Files

Variables disappear when a program ends. To keep data, such as notes, scores, settings or logs, you save it to a file. Python makes reading and writing files straightforward.

About this page: the code here runs in your browser, so files are saved in a temporary in-browser file system. They're kept while this page is open, so one example can read a file another example wrote, and they disappear when you reload the page. On your own computer, the same code reads and writes real files.

Writing a file

open(filename, mode) opens a file. The mode "w" means write: it creates the file, or replaces it if it already exists. The with statement closes the file automatically when the block ends:

with open("notes.txt", "w") as f:
    f.write("Buy milk\n")
    f.write("Call Ada\n")
    f.write("Learn Python\n")

print("Saved!")
Output

write() doesn't add a newline for you, so add \n yourself at the end of each line.

Reading a whole file

Mode "r" (read) is the default, so you can leave it out:

with open("notes.txt") as f:
    content = f.read()

print(content)
print(type(content), len(content), "characters")
Output

Reading line by line

Looping over a file gives you one line at a time. That's memory-friendly even for huge files:

with open("notes.txt") as f:
    for number, line in enumerate(f, start=1):
        print(number, line.strip())
Output

Each line still ends with \n, which is why we use strip(). Use readlines() to get all the lines as a list:

with open("notes.txt") as f:
    lines = f.readlines()

print(lines)
print([line.strip() for line in lines])
Output

Appending

Mode "a" (append) adds to the end of a file instead of replacing it:

with open("notes.txt", "a") as f:
    f.write("Go for a run\n")

with open("notes.txt") as f:
    print(f.read())
Output

File modes

Mode Meaning If the file exists If it doesn't
"r" Read (default) reads it FileNotFoundError
"w" Write erases it first creates it
"a" Append adds to the end creates it
"x" Create FileExistsError creates it

Add b for binary files such as images ("rb", "wb").

Careful with "w": opening an existing file in write mode erases its contents immediately, even if you never write anything.

Why use with?

Without with, you must remember to call close() yourself, and if an error happens first, the file stays open:

f = open("notes.txt")
print(f.readline().strip())
f.close()
Output

with guarantees the file is closed, even if an exception happens inside the block. Always prefer it.

Going deeper: Accents and emoji: set the encoding optional

A file stores bytes, not letters. The encoding decides how letters such as é, ñ or ☕ become bytes. If you don't choose one, Python uses your computer's default, which on Windows is often not UTF-8. A file with accents written on one machine can then come out garbled, or raise a UnicodeDecodeError, on another.

Passing encoding="utf-8" when you open the file avoids all of that:

with open("menu.txt", "w", encoding="utf-8") as f:
    f.write("Café crème ☕\n")

with open("menu.txt", encoding="utf-8") as f:
    print(f.read())
Output

UTF-8 can store every character in every language, and it's what the web uses. Make encoding="utf-8" a habit for every text file.

Going deeper: Working with paths using pathlib optional

The pathlib module treats a file path as an object with handy methods, instead of a plain string:

from pathlib import Path

path = Path("notes.txt")
path.write_text("Buy milk\nCall Ada\n", encoding="utf-8")

print(path.exists())
print(path.name, path.stem, path.suffix)
print(path.read_text(encoding="utf-8"))
Output

/ joins path pieces and uses the right separator for Windows, macOS or Linux:

from pathlib import Path

folder = Path("reports")
folder.mkdir(exist_ok=True)

report = folder / "2026" / "summary.txt"
print(report)
print(report.parent)
Output

write_text() and read_text() are great for small files. For line-by-line reading, path.open() works just like open().

Handling a missing file

Reading a file that doesn't exist raises FileNotFoundError. Catch it like any other exception:

try:
    with open("missing.txt") as f:
        print(f.read())
except FileNotFoundError:
    print("The file doesn't exist yet.")
Output

The os module can check first, and list or delete files:

import os

print(os.path.exists("notes.txt"))
print(os.path.exists("missing.txt"))
print(os.listdir("."))
Output

Writing and reading numbers

Files hold text, so convert numbers to strings when writing and back again when reading:

scores = [88, 92, 75, 64]

with open("scores.txt", "w") as f:
    for score in scores:
        f.write(f"{score}\n")

with open("scores.txt") as f:
    loaded = [int(line) for line in f]

print(loaded, "average:", sum(loaded) / len(loaded))
Output

CSV files

CSV (comma-separated values) is the simplest spreadsheet format. The csv module handles the details, such as commas inside quoted values:

import csv

rows = [
    ["name", "city", "score"],
    ["Ada", "London", 92],
    ["Grace", "New York", 88],
]

with open("people.csv", "w", newline="") as f:
    writer = csv.writer(f)
    writer.writerows(rows)

with open("people.csv") as f:
    for row in csv.DictReader(f):
        print(f"{row['name']} from {row['city']} scored {row['score']}")
Output

JSON files

JSON is the standard format for structured data on the web, and it maps directly onto Python dictionaries and lists:

import json

settings = {"theme": "dark", "font_size": 14, "recent": ["main.py", "notes.txt"]}

with open("settings.json", "w") as f:
    json.dump(settings, f, indent=2)

with open("settings.json") as f:
    print(f.read())

with open("settings.json") as f:
    loaded = json.load(f)

print(loaded["recent"][0])
Output

Exercises

Exercise 1: Write and read

Write the three lines red, green and blue to colors.txt, then read the file back and print each colour in upper case.

# write colors.txt, then read it back
Output

Exercise 2: Count lines and words

Create story.txt with the given text, then print how many lines and how many words it has. It should print Lines: 3 and Words: 15.

text = "Once upon a time\nthere was a small python\nwho loved to code all day\n"
Output

Exercise 3: Visit log

Write a function log_visit(name) that appends a line Visited by <name> to log.txt. Call it three times, then print the file.

def log_visit(name):
    pass
Output

Exercise 4: Save a high score

Save the dictionary to scores.json, load it back, and print the name with the highest score: Leo.

import json

high_scores = {"Mia": 1200, "Leo": 1850, "Ava": 990}
Output

File tools at a glance

A quick reference for later. f is a file opened with with open(...) as f:.

Code What it does
open(name, "w", encoding="utf-8") Opens a file for writing (replaces it). Use "a" to append and "r" (the default) to read
f.write(text) Writes a string; add \n yourself for new lines
f.writelines(lines) Writes every string in a list (again, no new lines added)
f.read() Reads the whole file into one string
f.readline() Reads the next line, including its \n
f.readlines() Reads all lines into a list
for line in f: Goes through the file one line at a time (memory-friendly)
line.strip() Removes the \n (and spaces) from the ends of a line
os.path.exists(name) Does the file exist? (import os first)
Path(name).read_text() / .write_text(text) Reads or writes a whole file in one step (from pathlib import Path)
json.dump(data, f, indent=2) Saves lists and dictionaries to a JSON file
json.load(f) Loads a JSON file back into lists and dictionaries
json.dumps(data) / json.loads(text) The same, but to and from a string instead of a file
csv.writer(f).writerow(row) Writes one row to a CSV file; writerows(rows) writes many
csv.reader(f) Reads a CSV file as lists of strings, one per row
csv.DictReader(f) Reads a CSV file as dictionaries, using the header row as keys

Summary

  • open(name, mode) opens a file: "r" reads, "w" writes (and erases), "a" appends.
  • with open(...) as f: closes the file automatically. Always use it.
  • f.read() reads everything, and for line in f: reads line by line. Use strip() to remove the \n.
  • f.write() writes text. Add \n yourself, and convert numbers with str() or f-strings.
  • A missing file raises FileNotFoundError, and os.path.exists() checks first.
  • Use the csv module for spreadsheets and json for structured data.