π§ͺ 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:
- Load the guest list (empty list if no file)
- Ask for a name, add it, save
- Print the full list 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,88
Read 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.