Skip to main content

07.1 - Reading & Writing Files

Theory 20 min Intermediate

Opening Files with open()

# Syntax
file = open(filename, mode, encoding=None)
ModeDescription
'r'Read (default) — error if file doesn't exist
'w'Write — creates file, overwrites if exists
'a'Append — creates file, adds to end
'x'Exclusive create — error if file exists
'r+'Read and write
'b'Binary mode (combine: 'rb', 'wb')

Always use with statement — it automatically closes the file even if an error occurs:

# ✅ Always use with
with open("data.txt", "r", encoding="utf-8") as f:
content = f.read()
# File is automatically closed here

# ❌ Manual close — risky
f = open("data.txt")
content = f.read()
f.close() # might not run if an exception occurs!

Reading Files

# Read entire file as one string
with open("poem.txt", "r", encoding="utf-8") as f:
content = f.read()

# Read line by line (memory-efficient for large files)
with open("data.txt") as f:
for line in f:
print(line.strip()) # strip removes trailing \n

# Read all lines into a list
with open("data.txt") as f:
lines = f.readlines() # ['line1\n', 'line2\n', ...]
lines = [line.strip() for line in f.readlines()]

# Read one line at a time
with open("data.txt") as f:
first = f.readline() # reads one line
second = f.readline() # reads next line

Writing Files

# Write (overwrites existing content)
with open("output.txt", "w", encoding="utf-8") as f:
f.write("Hello, World!\n")
f.write("Second line\n")

# Write multiple lines at once
lines = ["line 1\n", "line 2\n", "line 3\n"]
with open("output.txt", "w") as f:
f.writelines(lines)

# Append to existing file
with open("log.txt", "a") as f:
from datetime import datetime
f.write(f"{datetime.now().isoformat()} — Event logged\n")

pathlib — Modern Path Handling

pathlib.Path is the modern, object-oriented way to work with file paths:

from pathlib import Path

# Create paths
p = Path("data/input.txt")
home = Path.home()
cwd = Path.cwd()

# Path operations
p.parent # Path("data")
p.name # "input.txt"
p.stem # "input"
p.suffix # ".txt"
p.exists() # True/False
p.is_file() # True/False
p.is_dir() # True/False

# Read and write (no open() needed!)
text = p.read_text(encoding="utf-8")
p.write_text("new content", encoding="utf-8")
data = p.read_bytes()

# List files
for f in Path(".").glob("*.py"):
print(f)

# Create directories
Path("output/logs").mkdir(parents=True, exist_ok=True)

# Join paths (/ operator)
config_file = Path.home() / ".config" / "app" / "settings.json"

Encoding

Always specify encoding explicitly:

# UTF-8 is the standard — always use it
with open("file.txt", encoding="utf-8") as f:
content = f.read()

# Handle encoding errors
with open("file.txt", encoding="utf-8", errors="replace") as f:
content = f.read() # replaces bad chars with ?

Key Vocabulary

TermDefinition
open()Built-in function to open a file
Context managerwith block that handles setup and cleanup automatically
read()Read entire file as string
readlines()Read all lines as a list
write()Write a string to a file
pathlib.PathObject-oriented path manipulation
EncodingHow text is stored as bytes — always use utf-8
ModeHow the file is opened: r=read, w=write, a=append

Summary

  • Always use with open(...) — never manual .close()
  • encoding="utf-8" should always be specified for text files
  • Iterate over file object for memory-efficient line-by-line reading
  • pathlib.Path provides an elegant OOP interface for file system operations
  • Modes: r (read), w (write/overwrite), a (append), x (create new)