Site

File I/O — Python File Operations

Tutorial S5  •  Python / Learn

S5.0 What This Teaches

This tutorial covers file and path operations in Python:

S5.1 Opening Files

# Always use with - file closes even if an exception occurs
with open("notes.txt", "w") as f:
    f.write("Hello, file!\n")
    f.write("Second line.\n")

# Read modes
# "r"  - read text (default)
# "w"  - write text (creates or truncates)
# "a"  - append text
# "rb" - read binary
# "wb" - write binary

with open("notes.txt", "r") as f:
    content = f.read()   # read entire file as one string
print(content)
Outside a with block, a file handle is only closed when garbage collected. On Windows this can prevent other code from opening the file. Always use with.

S5.2 Reading Files

with open("notes.txt") as f:
    # Read entire file
    content = f.read()

with open("notes.txt") as f:
    # Read one line at a time (memory-efficient)
    line = f.readline()   # includes trailing \n
    while line:
        print(line, end="")
        line = f.readline()

with open("notes.txt") as f:
    # Read all lines into a list
    lines = f.readlines()   # each line includes \n

# Best for large files: iterate the file object directly
with open("notes.txt") as f:
    for line in f:
        print(line.strip())

S5.3 Writing Files

# Write a string
with open("output.txt", "w") as f:
    f.write("line one\n")
    f.write("line two\n")

# Write multiple lines at once
lines = ["alpha\n", "beta\n", "gamma\n"]
with open("output.txt", "w") as f:
    f.writelines(lines)   # writelines does not add newlines

# Append to existing file
with open("output.txt", "a") as f:
    f.write("appended\n")

# print() works with file=
with open("output.txt", "a") as f:
    print("printed line", file=f)   # adds newline automatically

S5.4 Working with Paths using pathlib

from pathlib import Path

p = Path("data/notes.txt")

print(p.name)        # "notes.txt"
print(p.stem)        # "notes"
print(p.suffix)      # ".txt"
print(p.parent)      # "data"
print(p.resolve())   # absolute path

# Build paths with /
config = Path.home() / ".config" / "app.json"

# Test existence
print(p.exists())
print(p.is_file())
print(p.is_dir())

# Convenience read/write (small files)
p.write_text("Hello from pathlib!")
text = p.read_text()

# Enumerate files
for f in Path(".").glob("*.txt"):
    print(f.name)

S5.5 Directory Operations

import os
from pathlib import Path

# Create directories
Path("mydir/subdir").mkdir(parents=True, exist_ok=True)

# List directory
for item in Path(".").iterdir():
    print(item.name, "dir" if item.is_dir() else "file")

# Recursive glob
for py_file in Path(".").rglob("*.py"):
    print(py_file)

# Delete
import shutil
Path("file.txt").unlink(missing_ok=True)   # delete file
shutil.rmtree("mydir")                     # delete directory tree

# os.path (older API, still common)
import os.path
print(os.path.join("a", "b", "c.txt"))
print(os.path.exists("notes.txt"))

S5.6 Binary Files

import struct

# Write binary: pack ints and floats
with open("data.bin", "wb") as f:
    f.write(struct.pack("<if", 42, 3.14))   # little-endian int + float

# Read binary
with open("data.bin", "rb") as f:
    raw = f.read(8)
    i, x = struct.unpack("<if", raw)
    print(i, x)   # 42 3.14

# Simple bytes
with open("bytes.bin", "wb") as f:
    f.write(bytes(range(10)))

with open("bytes.bin", "rb") as f:
    data = f.read()
    print(list(data))   # [0, 1, 2, ..., 9]

S5.7 Example - All Together

# File I/O - write CSV and read it back, computing average score.

from pathlib import Path

csv_path = Path("scores.csv")
records = [("Alice", 92), ("Bob", 78), ("Carol", 95)]

# Write CSV
with csv_path.open("w") as f:
    f.write("Name,Score\n")
    for name, score in records:
        f.write(f"{name},{score}\n")

# Read and process
total = 0
count = 0
with csv_path.open() as f:
    next(f)   # skip header
    for line in f:
        _, score = line.strip().split(",")
        total += int(score)
        count += 1

print(f"Average score: {total / count:.1f}")
Expected output:
Average score: 88.3

S5.8 Exercise

Exercise
  • Write a function that counts the number of lines, words, and characters in a text file (like wc on Unix). Test it on any file.
  • Use pathlib.Path.rglob("*.py") to find all Python files in the current directory tree. Print each path relative to the current directory.
  • Write a binary file containing a sequence of integers using struct.pack, then read it back and print the sum.

S5.9 Common Mistakes

Opening a file without with

f = open("data.txt")
content = f.read()
# f.close() forgotten - handle stays open until GC
# Use with open("data.txt") as f: instead

Opening a binary file in text mode

with open("image.png") as f:   # text mode on binary data
    data = f.read()   # UnicodeDecodeError or corruption
with open("image.png", "rb") as f:   # correct
    data = f.read()

Using os.path when pathlib is available

pathlib.Path is the modern API. It's object-oriented, composable with /, and avoids many string-concatenation errors. Prefer it over os.path in new code.

S5.10 Key Terms

TermMeaning
open()Built-in that returns a file object; mode controls read/write/binary
withEnsures the file is closed after the block, even on exception
read()Reads the entire file or up to n bytes/chars into a string or bytes
readline()Reads one line including the trailing newline
write()Writes a string or bytes; does not add a newline
pathlib.PathObject-oriented path; supports /, glob(), read_text(), write_text()
glob / rglobPattern-matching file search; rglob is recursive
structStandard library module for packing/unpacking binary data