File I/O & JSON
Read files, write files, and parse JSON β the format every API speaks. This is how you save data and talk to the world.
Learning Objectives
- Read and write text files with
open() - Use context managers (
with) for safe file handling - Parse and generate JSON with
jsonmodule - Read and write CSV files
- Handle file paths with
pathlib - Load .env files with
python-dotenv
Reading & Writing Files
python
# Always use "with" β it auto-closes the file even if errors occur
# Read entire file
with open("config.txt", "r") as f:
content = f.read()
print(content)
# Read line by line (memory efficient for large files)
with open("app.log", "r") as f:
for line in f:
if "ERROR" in line:
print(line.strip())
# Read into a list of lines
with open("data.txt", "r") as f:
lines = f.readlines()
# Write to file (creates or overwrites)
with open("output.txt", "w") as f:
f.write("Hello, AI Engineer!\n")
f.write("Another line\n")
# Append to file (doesn't overwrite)
with open("log.txt", "a") as f:
f.write("New log entry\n")JSON β The Language of APIs
Every API you call returns JSON. Every config file is JSON. You MUST be fluent with the json module.
python
import json
# Parse JSON string β Python dict
api_response = '{"model": "gpt-4o", "tokens": 150}'
data = json.loads(api_response)
print(data["model"]) # "gpt-4o"
# Python dict β JSON string
config = {"model": "gpt-4o", "temperature": 0.7}
json_string = json.dumps(config, indent=2)
print(json_string)
# Read JSON file
with open("config.json", "r") as f:
config = json.load(f)
# Write JSON file
output = {"results": [{"score": 0.95, "text": "RAG is..."}]}
with open("results.json", "w") as f:
json.dump(output, f, indent=2)JSONβPython Type Mapping
text
JSON Python βββββ ββββββ object dict array list string str number (int) int number (real) float true True false False null None β οΈ Python-only types that DON'T exist in JSON: - tuple β becomes a list - set β use list(set) first - datetime β convert to ISO string first - bytes β decode to string first
CSV Files
python
import csv
# Read CSV
with open("expenses.csv", "r") as f:
reader = csv.DictReader(f) # each row = dict with header keys
for row in reader:
print(row["description"], row["amount"])
# Write CSV
expenses = [
{"description": "Coffee", "amount": 4.50, "category": "Food"},
{"description": "Uber", "amount": 12.00, "category": "Transport"},
]
with open("expenses.csv", "w", newline="") as f:
writer = csv.DictWriter(f, fieldnames=["description", "amount", "category"])
writer.writeheader()
writer.writerows(expenses)pathlib β Modern Path Handling
python
from pathlib import Path
# Create Path objects (much better than string concatenation)
data_dir = Path("data")
config_file = data_dir / "config.json" # data/config.json
# Check existence
config_file.exists() # True/False
config_file.is_file() # True/False
data_dir.is_dir() # True/False
# Create directories
data_dir.mkdir(exist_ok=True, parents=True)
# List files
for file in data_dir.glob("*.json"):
print(file)
# Read/write with Path (simple and clean)
text = config_file.read_text() # read entire file
config_file.write_text(json.dumps(data)) # write entire fileLoading .env Files
python
from dotenv import load_dotenv
import os
load_dotenv() # reads .env file into os.environ
api_key = os.environ.get("OPENAI_API_KEY")
model = os.environ.get("DEFAULT_MODEL", "gpt-4o-mini")
if not api_key:
raise ValueError("OPENAI_API_KEY not found in .env")Exercise β Config Manager
Write a Python script that: (1) loads a JSON config file, (2) merges it with any values from .env (env overrides JSON), (3) validates required keys exist, and (4) saves the final config to a new JSON file.