TechLead
Lesson 7 of 25
5 min read
Python

File Handling

Learn to read, write, and manage files in Python including text, CSV, JSON, and binary files

Reading and Writing Text Files

File handling is a fundamental skill in Python. The built-in open() function provides a clean interface for reading and writing files. Always use the with statement (context manager) to ensure files are properly closed, even if an exception occurs.

# Writing to a file
with open("output.txt", "w") as f:
    f.write("Hello, World!\n")
    f.write("Second line\n")

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

# Reading entire file
with open("output.txt", "r") as f:
    content = f.read()
    print(content)

# Reading line by line (memory efficient for large files)
with open("output.txt", "r") as f:
    for line in f:
        print(line.strip())  # strip() removes trailing newline

# Reading all lines into a list
with open("output.txt", "r") as f:
    lines = f.readlines()
    print(lines)  # ['Line 1\n', 'Line 2\n', 'Line 3\n']

# Appending to a file
with open("output.txt", "a") as f:
    f.write("Appended line\n")

# Reading with encoding
with open("unicode.txt", "r", encoding="utf-8") as f:
    content = f.read()

Working with CSV Files

The csv module provides robust CSV reading and writing that handles edge cases like quoted fields, different delimiters, and embedded newlines. For large-scale data work, consider using pandas instead.

import csv

# Writing CSV
data = [
    ["Name", "Age", "City"],
    ["Alice", 30, "New York"],
    ["Bob", 25, "London"],
    ["Charlie", 35, "Tokyo"],
]

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

# Reading CSV
with open("people.csv", "r") as f:
    reader = csv.reader(f)
    header = next(reader)  # Skip header
    for row in reader:
        name, age, city = row
        print(f"{name} is {age} from {city}")

# DictReader/DictWriter (more readable)
with open("people.csv", "r") as f:
    reader = csv.DictReader(f)
    for row in reader:
        print(f"{row['Name']} lives in {row['City']}")

# Writing with DictWriter
with open("output.csv", "w", newline="") as f:
    fieldnames = ["name", "email", "role"]
    writer = csv.DictWriter(f, fieldnames=fieldnames)
    writer.writeheader()
    writer.writerow({"name": "Alice", "email": "alice@test.com", "role": "Engineer"})

Working with JSON

JSON is the lingua franca of APIs and configuration files. Python's json module makes it easy to serialize Python objects to JSON and deserialize JSON back to Python objects.

import json

# Python to JSON
data = {
    "name": "Alice",
    "age": 30,
    "hobbies": ["reading", "coding", "hiking"],
    "address": {
        "city": "New York",
        "country": "USA"
    },
    "active": True,
    "score": None
}

# Write JSON to file
with open("data.json", "w") as f:
    json.dump(data, f, indent=2)

# Read JSON from file
with open("data.json", "r") as f:
    loaded = json.load(f)
    print(loaded["name"])  # "Alice"

# Convert to/from JSON strings
json_string = json.dumps(data, indent=2)
parsed = json.loads(json_string)

# Custom serialization for unsupported types
from datetime import datetime

class DateEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, datetime):
            return obj.isoformat()
        return super().default(obj)

data_with_date = {"created": datetime.now()}
print(json.dumps(data_with_date, cls=DateEncoder))

Path Handling with pathlib

The pathlib module (Python 3.4+) provides an object-oriented interface for filesystem paths. It is more readable and less error-prone than using string manipulation with os.path.

from pathlib import Path

# Creating paths
home = Path.home()
project = Path("/Users/alice/projects/myapp")
config = project / "config" / "settings.json"  # Join with /

# Path properties
print(config.name)      # "settings.json"
print(config.stem)      # "settings"
print(config.suffix)    # ".json"
print(config.parent)    # /Users/alice/projects/myapp/config

# Check existence
print(config.exists())
print(config.is_file())
print(config.is_dir())

# Reading and writing (convenience methods)
path = Path("example.txt")
path.write_text("Hello, World!")
content = path.read_text()

path.write_bytes(b"\x00\x01\x02")
data = path.read_bytes()

# Directory operations
src = Path("src")
src.mkdir(parents=True, exist_ok=True)

# Iterate over directory contents
for item in Path(".").iterdir():
    print(item.name)

# Glob pattern matching
for py_file in Path(".").glob("**/*.py"):
    print(py_file)

# Rename and delete
path.rename("new_name.txt")
# path.unlink()  # Delete file

Key Takeaways

  • Always use 'with': Context managers ensure files are properly closed
  • Use pathlib: Prefer Path objects over os.path string manipulation
  • csv module: Use DictReader/DictWriter for readable CSV processing
  • json module: Use json.dump/load for files, json.dumps/loads for strings

Continue Learning