File operations are fundamental. Here's how to do them properly.
Reading Files
# Basic reading
with open("file.txt") as f:
content = f.read()
# Read lines
with open("file.txt") as f:
lines = f.readlines() # List of lines
# Iterate lines (memory efficient)
with open("file.txt") as f:
for line in f:
process(line.strip())Writing Files
# Write (overwrites)
with open("file.txt", "w") as f:
f.write("Hello, World!")
# Append
with open("file.txt", "a") as f:
f.write("\nNew line")
# Write lines
with open("file.txt", "w") as f:
f.writelines(["line1\n", "line2\n"])File Modes
| Mode | Description |
|---|---|
r | Read (default) |
w | Write (overwrites) |
a | Append |
x | Create (fails if exists) |
b | Binary mode |
+ | Read and write |
# Binary
with open("image.png", "rb") as f:
data = f.read()
# Read and write
with open("file.txt", "r+") as f:
content = f.read()
f.write("appended")pathlib (Modern Approach)
from pathlib import Path
# Create path
path = Path("folder/file.txt")
# Read/write
content = path.read_text()
path.write_text("Hello!")
# Binary
data = path.read_bytes()
path.write_bytes(data)Path Operations
from pathlib import Path
path = Path("/home/user/documents/file.txt")
# Components
path.name # "file.txt"
path.stem # "file"
path.suffix # ".txt"
path.parent # Path("/home/user/documents")
path.parts # ('/', 'home', 'user', 'documents', 'file.txt')
# Build paths
new_path = path.parent / "other.txt"Checking Files
from pathlib import Path
path = Path("file.txt")
path.exists() # True/False
path.is_file() # Is regular file
path.is_dir() # Is directory
path.is_absolute() # Is absolute pathDirectory Operations
from pathlib import Path
folder = Path("my_folder")
# Create directory
folder.mkdir()
folder.mkdir(parents=True, exist_ok=True)
# List contents
for item in folder.iterdir():
print(item)
# Find files
for py_file in folder.glob("*.py"):
print(py_file)
# Recursive glob
for py_file in folder.rglob("*.py"):
print(py_file)Working with CSV
import csv
# Read CSV
with open("data.csv") as f:
reader = csv.reader(f)
for row in reader:
print(row)
# Read as dicts
with open("data.csv") as f:
reader = csv.DictReader(f)
for row in reader:
print(row["name"], row["email"])
# Write CSV
with open("output.csv", "w", newline="") as f:
writer = csv.writer(f)
writer.writerow(["name", "email"])
writer.writerow(["Owen", "owen@example.com"])Working with JSON
import json
from pathlib import Path
# Read JSON
data = json.loads(Path("data.json").read_text())
# Write JSON
Path("output.json").write_text(
json.dumps(data, indent=2)
)
# Or with file handle
with open("data.json") as f:
data = json.load(f)
with open("output.json", "w") as f:
json.dump(data, f, indent=2)Encoding
# Specify encoding (important!)
with open("file.txt", encoding="utf-8") as f:
content = f.read()
# pathlib
path.read_text(encoding="utf-8")
path.write_text(content, encoding="utf-8")Always specify encoding to avoid platform-dependent issues.
Temporary Files
import tempfile
# Temporary file (auto-deleted)
with tempfile.NamedTemporaryFile(mode="w", delete=False) as f:
f.write("temporary content")
temp_path = f.name
# Temporary directory
with tempfile.TemporaryDirectory() as tmpdir:
# Use tmpdir
pass # Deleted when exitingCopying and Moving
import shutil
from pathlib import Path
# Copy file
shutil.copy("source.txt", "dest.txt")
shutil.copy2("source.txt", "dest.txt") # Preserves metadata
# Copy directory
shutil.copytree("source_dir", "dest_dir")
# Move
shutil.move("source.txt", "dest.txt")
# Delete
Path("file.txt").unlink() # Delete file
shutil.rmtree("directory") # Delete directorySafe File Operations
from pathlib import Path
import tempfile
import shutil
def safe_write(path: Path, content: str) -> None:
"""Write atomically to avoid corruption."""
path = Path(path)
# Write to temp file first
with tempfile.NamedTemporaryFile(
mode="w",
dir=path.parent,
delete=False
) as f:
f.write(content)
temp_path = Path(f.name)
# Atomic rename
temp_path.replace(path)Error Handling
from pathlib import Path
path = Path("file.txt")
try:
content = path.read_text()
except FileNotFoundError:
print("File not found")
except PermissionError:
print("Permission denied")
except IsADirectoryError:
print("Expected file, got directory")My Patterns
from pathlib import Path
import json
def load_json(path: str | Path) -> dict:
"""Load JSON file with error handling."""
path = Path(path)
if not path.exists():
return {}
return json.loads(path.read_text(encoding="utf-8"))
def save_json(path: str | Path, data: dict) -> None:
"""Save JSON file with pretty printing."""
path = Path(path)
path.parent.mkdir(parents=True, exist_ok=True)
path.write_text(
json.dumps(data, indent=2, ensure_ascii=False),
encoding="utf-8"
)Use pathlib. Specify encoding. Handle errors. Use context managers.
React to this post: