Python Basics — File Handling Exercises
Practice Exercises — File Handling
Test your understanding of reading files, writing files, context managers, CSV, and JSON.
Exercise 1: Word Counter
Write a function count_words(filename) that reads a text file and returns a dictionary mapping each word (lowercased) to its count. Ignore punctuation.
Test with:
Hello world hello Python
Python is great and hello
Expected output: {'hello': 3, 'world': 1, 'python': 2, 'is': 1, 'great': 1, 'and': 1}
Show Solution
import string
def count_words(filename):
word_counts = {}
with open(filename, "r") as f:
for line in f:
# Remove punctuation and lowercase
cleaned = line.translate(
str.maketrans("", "", string.punctuation)
).lower()
for word in cleaned.split():
word_counts[word] = word_counts.get(word, 0) + 1
return word_counts
# Test
counts = count_words("sample.txt")
for word, count in sorted(counts.items()):
print(f"{word}: {count}")
Exercise 2: CSV Report Generator
Given a list of student dictionaries, write them to a CSV file and then read the file back, calculating the average score.
students = [
{"name": "Alice", "math": 92, "science": 88, "english": 95},
{"name": "Bob", "math": 78, "science": 82, "english": 70},
{"name": "Carol", "math": 95, "science": 91, "english": 89},
{"name": "Dave", "math": 65, "science": 72, "english": 80},
]
Expected: Write students.csv, read it back, print each student’s average.
Show Solution
import csv
students = [
{"name": "Alice", "math": 92, "science": 88, "english": 95},
{"name": "Bob", "math": 78, "science": 82, "english": 70},
{"name": "Carol", "math": 95, "science": 91, "english": 89},
{"name": "Dave", "math": 65, "science": 72, "english": 80},
]
# Write to CSV
with open("students.csv", "w", newline="") as f:
fieldnames = ["name", "math", "science", "english"]
writer = csv.DictWriter(f, fieldnames=fieldnames)
writer.writeheader()
writer.writerows(students)
print("CSV file written!\n")
# Read back and calculate averages
with open("students.csv", "r") as f:
reader = csv.DictReader(f)
print(f"{'Name':<10} {'Math':>6} {'Science':>8} {'English':>8} {'Average':>8}")
print("-" * 44)
for row in reader:
scores = [int(row["math"]), int(row["science"]), int(row["english"])]
avg = sum(scores) / len(scores)
print(f"{row['name']:<10} {row['math']:>6} {row['science']:>8} {row['english']:>8} {avg:>8.1f}")
Exercise 3: JSON Configuration Manager
Create a ConfigManager class that:
- Loads settings from a JSON file (or creates defaults if the file doesn’t exist)
- Allows getting and setting values
- Saves changes back to the file
Show Solution
import json
import os
class ConfigManager:
DEFAULTS = {
"theme": "light",
"language": "en",
"font_size": 14,
"auto_save": True,
"recent_files": [],
}
def __init__(self, filename="config.json"):
self.filename = filename
self.settings = self._load()
def _load(self):
"""Load settings from file, or return defaults."""
if os.path.exists(self.filename):
with open(self.filename, "r") as f:
saved = json.load(f)
# Merge with defaults (keeps new default keys)
merged = {**self.DEFAULTS, **saved}
return merged
return dict(self.DEFAULTS)
def get(self, key, default=None):
"""Get a setting value."""
return self.settings.get(key, default)
def set(self, key, value):
"""Set a setting value."""
self.settings[key] = value
def save(self):
"""Save current settings to file."""
with open(self.filename, "w") as f:
json.dump(self.settings, f, indent=4)
def reset(self):
"""Reset to default settings."""
self.settings = dict(self.DEFAULTS)
self.save()
def __repr__(self):
return f"ConfigManager({json.dumps(self.settings, indent=2)})"
# Test
config = ConfigManager("test_config.json")
print(f"Theme: {config.get('theme')}") # light
print(f"Font size: {config.get('font_size')}") # 14
config.set("theme", "dark")
config.set("font_size", 16)
config.save()
# Reload and verify
config2 = ConfigManager("test_config.json")
print(f"Theme: {config2.get('theme')}") # dark
print(f"Font size: {config2.get('font_size')}") # 16
# Cleanup
os.remove("test_config.json")
Exercise 4: Log File Analyzer
Write a function that reads a log file, extracts entries by severity level (INFO, WARNING, ERROR), and writes a summary report.
Sample log file (app.log):
2025-01-15 10:30:00 INFO Application started
2025-01-15 10:30:05 INFO User login: alice
2025-01-15 10:31:12 WARNING Disk usage at 85%
2025-01-15 10:32:00 ERROR Database connection failed
2025-01-15 10:32:30 INFO Retry successful
2025-01-15 10:35:00 ERROR Timeout on API call
2025-01-15 10:36:00 WARNING Memory usage high
Show Solution
from collections import defaultdict
def analyze_log(input_file, output_file):
"""Analyze log file and write summary report."""
counts = defaultdict(int)
entries = defaultdict(list)
with open(input_file, "r") as f:
for line in f:
line = line.strip()
if not line:
continue
parts = line.split(maxsplit=3)
if len(parts) >= 4:
date, time, level, message = parts
counts[level] += 1
entries[level].append(f" [{date} {time}] {message}")
# Write report
total = sum(counts.values())
with open(output_file, "w") as f:
f.write("=" * 50 + "\n")
f.write("LOG ANALYSIS REPORT\n")
f.write("=" * 50 + "\n\n")
f.write(f"Total entries: {total}\n\n")
for level in ["ERROR", "WARNING", "INFO"]:
count = counts.get(level, 0)
pct = (count / total * 100) if total else 0
f.write(f"{level}: {count} ({pct:.1f}%)\n")
f.write("\n" + "-" * 50 + "\n")
f.write("ERRORS:\n")
for entry in entries.get("ERROR", []):
f.write(entry + "\n")
f.write("\nWARNINGS:\n")
for entry in entries.get("WARNING", []):
f.write(entry + "\n")
print(f"Report written to {output_file}")
return dict(counts)
# Test
results = analyze_log("app.log", "log_report.txt")
print(f"Summary: {results}")
Exercise 5: File Format Converter (CSV ↔ JSON)
Write two functions:
csv_to_json(csv_file, json_file)— convert a CSV file to a JSON filejson_to_csv(json_file, csv_file)— convert a JSON file (list of objects) to a CSV file
Show Solution
import csv
import json
def csv_to_json(csv_file, json_file):
"""Convert CSV file to JSON file."""
records = []
with open(csv_file, "r") as f:
reader = csv.DictReader(f)
for row in reader:
records.append(row)
with open(json_file, "w") as f:
json.dump(records, f, indent=4)
print(f"Converted {len(records)} records: {csv_file} → {json_file}")
def json_to_csv(json_file, csv_file):
"""Convert JSON file (list of objects) to CSV file."""
with open(json_file, "r") as f:
records = json.load(f)
if not records:
print("No records to convert")
return
# Use keys from first record as fieldnames
fieldnames = list(records[0].keys())
with open(csv_file, "w", newline="") as f:
writer = csv.DictWriter(f, fieldnames=fieldnames)
writer.writeheader()
writer.writerows(records)
print(f"Converted {len(records)} records: {json_file} → {csv_file}")
# Test: Create a CSV, convert to JSON, convert back
test_csv = "test_data.csv"
test_json = "test_data.json"
test_csv_back = "test_data_back.csv"
# Create test CSV
with open(test_csv, "w", newline="") as f:
writer = csv.writer(f)
writer.writerow(["name", "age", "city"])
writer.writerow(["Alice", "30", "NYC"])
writer.writerow(["Bob", "25", "LA"])
writer.writerow(["Carol", "35", "Chicago"])
# Convert CSV → JSON
csv_to_json(test_csv, test_json)
# Verify JSON
with open(test_json) as f:
print(json.dumps(json.load(f), indent=2))
# Convert JSON → CSV
json_to_csv(test_json, test_csv_back)
# Verify CSV
with open(test_csv_back) as f:
print(f.read())
# Cleanup
import os
for f in [test_csv, test_json, test_csv_back]:
os.remove(f)
Scoring Guide
| Score | Level |
|---|---|
| 5/5 | Excellent — You handle files like a pro |
| 3-4/5 | Good — Solid understanding of file I/O |
| 1-2/5 | Keep practicing — Review context managers, CSV, and JSON modules |
Next chapter: Error Handling →