What’s one thing you learned? What’s still confusing?
Mini-Project: Robust Calculator
Build a calculator that survives any bad input using try/except and validation loops.
File I/O: Read, Write & Persist Data
Open files with `with`, handle errors gracefully, and work with pathlib, json, and csv.
Mini-Project: Todo App
Build a CLI todo app with file persistence — your first program that remembers state between runs.
Interactive Labs for This Track
Loop Visualizer
You're a factory robot repeating the same task on an assembly line — watch how loops automate repetitive work
List Slicing
You have a playlist of 50 songs — grab just tracks 10 through 20 with a single slice expression
Sorting Algorithms
You're organizing a library of 10,000 books — which sorting method is fastest?
Ask questions, share insights
When Python shows red text, it's not yelling at you — it's telling you exactly what went wrong. Let's learn to read it.
print(username)
# NameError: name 'username' is not definedusername = "alex" # ← define it first
print(username) # ✅ Now it worksWhat error does this raise? usernme = "alex" print(username)
usernme (missing 'a'), but line 2 tries to read username — which Python has never seen. Python doesn't auto-correct typos; it raises NameError: name 'username' is not defined. The error message names the EXACT misspelled identifier, which is your big clue. 90% of NameErrors are typos in variable names — the other 10% are using a variable before it was assigned, or forgetting to import a module.age = "25"
print(age + 1)
# TypeError: can only concatenate str (not "int") to str"25" is a string (text), 1 is a number — you can't add them directly.age = int("25") # ← convert to integer first
print(age + 1) # ✅ 26fruits = ["apple", "banana", "cherry"]
print(fruits[5])
# IndexError: list index out of rangeprint(fruits[2]) # ✅ "cherry" — the last element
print(fruits[-1]) # ✅ Also "cherry" — negative indices count from endWhen errors happen inside functions, Python shows a full traceback:
Traceback (most recent call last):
File "app.py", line 12, in main
result = calculate(data)
File "app.py", line 7, in calculate
return data[0] / data[1]
ZeroDivisionError: division by zero
ZeroDivisionError: division by zero ← this is your answer — you divided by zeroFile "app.py", line 7, in calculate ← happened in the calculate function, line 7return data[0] / data[1] ← this specific line caused itThe bottom line tells you what. The lines above trace back how you got there.
Without error handling, one bad input crashes your entire program. With try/except, you catch the error and respond sensibly.
This code calls input(). Python here can't pause to ask you, so type the answers below before running — one value per line, in the order the program asks for them.
# Without error handling — crashes on bad input
age = int(input("Enter your age: ")) # ← crashes if user types "abc"
# With error handling — graceful recovery
try:
age = int(input("Enter your age: "))
print(f"You are {age} years old")
except ValueError:
print("That's not a valid number. Please enter a digit like 25.")What gets printed? try: print("A") x = 10 / 0 print("B") except ZeroDivisionError: print("C") print("D")
10 / 0 raises ZeroDivisionError — execution IMMEDIATELY jumps to the matching except block, skipping line "B" entirely. "C" prints inside the handler. After the try/except, execution resumes normally and "D" prints. Key insight: once an exception fires, NOTHING after it in the try block runs — even non-risky lines like print("B") get skipped. This is why you keep try blocks focused on just the risky operation.This code calls input(). Python here can't pause to ask you, so type the answers below before running — one value per line, in the order the program asks for them.
try:
number = int(input("Enter a number: "))
result = 100 / number
print(f"100 / {number} = {result}")
except ValueError:
print("Please enter a valid number")
except ZeroDivisionError:
print("Can't divide by zero!")
except Exception as e:
print(f"Something unexpected happened: {e}")try:
file = open("data.txt", "r")
content = file.read()
except FileNotFoundError:
print("File not found — check the filename")
else:
# Runs ONLY if no exception occurred
print(f"File loaded: {len(content)} characters")
finally:
# ALWAYS runs — perfect for cleanup
print("Done attempting to read file")What prints, in what order? try: x = int("abc") except ValueError: print("caught") finally: print("cleanup")
int("abc") raises ValueError → the except block fires and prints "caught". THEN the finally block runs and prints "cleanup". The order is fixed: try → (except if there's an error) → finally. Crucially, finally runs EVEN IF the except block also raises a new error, or even if the original error was never caught. This makes it the right place for cleanup that absolutely must happen — closing files, releasing locks, restoring state.Sometimes you want to raise an error when something is logically wrong — even if Python wouldn't crash on its own.
def calculate_age(birth_year: int) -> int:
if birth_year < 1900 or birth_year > 2026:
raise ValueError(f"Birth year {birth_year} doesn't seem right")
return 2026 - birth_year
try:
age = calculate_age(1850)
except ValueError as e:
print(f"Error: {e}") # "Error: Birth year 1850 doesn't seem right"When your code doesn't work:
# Debugging with print — add temporarily, remove when fixed
def process_data(items):
print(f"DEBUG: items = {items}") # ← what did we receive?
total = 0
for item in items:
print(f"DEBUG: item = {item}, type = {type(item)}") # ← what is each item?
total += item
print(f"DEBUG: total = {total}") # ← what are we returning?
return totalInteractive Lab
Step through code line by line and watch exactly where errors occur
This program is supposed to catch ONLY bad number inputs and print a friendly message. Instead, a bare except: also hides a typo in the print line, so every call silently returns None. Fix the handler so it catches the right exception, and fix the typo it was hiding.
Bad age: twelve None 25
A user types 'hello' when your code expects a number and runs int('hello'). What error occurs?