๐งช Practice: Errors & Files
Failure handling and persistence, under your fingers. Five exercises, solutions at the bottom.
Exercise 1 โ The unbreakable input
Write a function get_positive_number(prompt) that keeps asking until the user enters a valid positive number (decimals allowed). No crash should ever be possible.
weight = get_positive_number("Enter weight (kg): ")
print(f"Got: {weight}")Exercise 2 โ Safe division calculator
Ask for two numbers and print the division. Handle BOTH failure modes: non-numeric input and zero denominator โ each with its own friendly message.
Exercise 3 โ The guest list (JSON persistence)
Create guests.json-backed app:
Run the script 3 times with different names โ all names should accumulate.
Exercise 4 โ Config loader with defaults
A config file settings.json may or may not exist, and may be missing keys. Write a loader that returns a dict with these defaults filled in:
DEFAULTS = {"theme": "dark", "volume": 50, "notifications": True}If the file exists, its values override defaults; missing keys fall back to defaults.
Exercise 5 โ CSV to report
Given marks.csv:
name,subject,marks
Aarav,Math,85
Aarav,Science,90
Diya,Math,95
Diya,Science,88Read it with csv.DictReader and print each student's total marks:
Aarav: 175
Diya: 183*(Hint: accumulate into a dict keyed by name โ the counting pattern from Module 5, upgraded.)*
Solutions
Exercise 1:
def get_positive_number(prompt):
while True:
try:
value = float(input(prompt))
if value <= 0:
print("Must be positive!")
continue
return value
except ValueError:
print("That's not a number โ try again")
weight = get_positive_number("Enter weight (kg): ")
print(f"Got: {weight}")Exercise 2:
try:
a = float(input("Numerator: "))
b = float(input("Denominator: "))
print(f"Result: {a / b}")
except ValueError:
print("Numbers only, please")
except ZeroDivisionError:
print("Cannot divide by zero")Exercise 3:
import json
import os
FILE = "guests.json"
guests = []
if os.path.exists(FILE):
with open(FILE) as f:
guests = json.load(f)
name = input("Guest name: ")
guests.append(name)
with open(FILE, "w") as f:
json.dump(guests, f, indent=2)
print("Guests so far:", guests)Exercise 4:
import json
import os
DEFAULTS = {"theme": "dark", "volume": 50, "notifications": True}
settings = DEFAULTS.copy()
if os.path.exists("settings.json"):
try:
with open("settings.json") as f:
saved = json.load(f)
settings.update(saved) # saved values override defaults
except json.JSONDecodeError:
print("Settings file corrupted โ using defaults")
print(settings)(dict.update(other) merges โ other's keys win. The try/except guards against a corrupted file, because a settings file should never crash the app.)
Exercise 5:
import csv
totals = {}
with open("marks.csv") as f:
for row in csv.DictReader(f):
name = row["name"]
marks = int(row["marks"])
if name in totals:
totals[name] += marks
else:
totals[name] = marks
for name, total in totals.items():
print(f"{name}: {total}")โ Module 8 Checkpoint
Errors handled, files persisting, formats parsed. Your programs now survive contact with real users and remember between runs โ two traits that separate toys from tools.
Next module: Object-Oriented Python โ organizing code the way big projects do.