Learn / Programming / Python / File Handling

Python · Lesson 11 of 15

File Handling

Read and write text files safely with context managers.

  • Intermediate
  • 12 min read
  • 3 objectives

Before this lessonLesson 10: Inheritance and Special Methods

What you will learn

  • Use with open()
  • Read and write text
  • Handle missing files

Real programs read configuration, process logs and save results, all of which means working with files. Python's open() gives you a file object, and the safest way to use it is inside a with block. The block guarantees the file is closed when you leave it, even if an error happens.

Why programs need files

Variables disappear the moment your program ends. A file is how information survives: settings, saved games, reports, logs. Reading and writing files lets your program remember things between runs, and lets it work with data created by other people and tools.

Think of a file as a notebook. To use it you open it, then read or write, then close it. Python's with statement does the closing for you, even when something goes wrong.

Writing a file

The second argument is the mode: "w" writes and erases any existing content, "a" appends, "r" reads (the default). Always pass encoding="utf-8" so text behaves the same on every operating system.

with open("notes.txt", "w", encoding="utf-8") as f:
    f.write("first line\n")
    f.write("second line\n")

Reading a file

f.read() returns the whole file as one string, f.readlines() returns a list of lines, and looping over the file object reads one line at a time, which keeps memory use low for large files.

with open("notes.txt", encoding="utf-8") as f:
    for line in f:
        print(line.strip())
Output
first line
second line

strip() removes the trailing newline character that every line carries.

Appending and paths

Use mode "a" to add to the end of a file without erasing it. For building paths that work on Windows, macOS and Linux, prefer pathlib over string concatenation.

from pathlib import Path

path = Path("data") / "log.txt"
path.parent.mkdir(exist_ok=True)
with path.open("a", encoding="utf-8") as f:
    f.write("started\n")
print(path.exists(), path.read_text(encoding="utf-8"))

Handling missing files

Opening a file that does not exist raises FileNotFoundError. Catch that specific exception to give a helpful fallback.

try:
    with open("missing.txt", encoding="utf-8") as f:
        data = f.read()
except FileNotFoundError:
    data = ""
    print("no file, using empty data")
Output
no file, using empty data

The three modes you need

  • "r" read (the default): fails if the file does not exist.
  • "w" write: creates the file, erasing anything already there.
  • "a" append: adds to the end without erasing.

Write, then read back

with open("notes.txt", "w") as f:
    f.write("first line\n")
    f.write("second line\n")

with open("notes.txt", "a") as f:
    f.write("third line\n")

with open("notes.txt") as f:
    print(f.read())
Output
first line
second line
third line

Reading line by line

For big files do not load everything at once. Looping over the file gives you one line at a time using very little memory. Each line ends with \n, so call .strip() to remove it.

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

Worked example: total a CSV of expenses

with open("expenses.csv", "w") as f:
    f.write("item,amount\ncoffee,3.5\nbooks,20\ntrain,12.25\n")

total = 0
with open("expenses.csv") as f:
    next(f)                      # skip the header row
    for line in f:
        item, amount = line.strip().split(",")
        total += float(amount)

print(f"Total: {total:.2f}")
Output
Total: 35.75

Handling a missing file

try:
    with open("does-not-exist.txt") as f:
        data = f.read()
except FileNotFoundError:
    data = ""
    print("No file yet, starting empty")
print(repr(data))
Output
No file yet, starting empty
''

Key takeaways

  • Open files with with open(path, mode) as f so they always close.
  • r reads, w overwrites, a appends.
  • Loop over a file to read it line by line; .strip() removes the newline.
  • Catch FileNotFoundError when a file might not exist yet.
# Write your solution here
Up next · Lesson 12Error Handlingtry/except/finally and raising your own exceptions.