Students read music.csv into a list of dictionaries with csv.DictReader, find values by row and key, learn that every value from a CSV is text, then filter and count rows and build a genre finder.
Load these into Waypoints Prepare: choose Load URL and paste the copied address, or download the file and import it. In Prepare, the worksheet's Teacher edition shows the answers; the student copy hides them.
Predict and Run 10 min · Investigate 15 min · Modify 15 min · Make 10 min
Read the unit primer first. This course runs in the Python playground (real Python in the browser, Pyodide). The first load takes a few seconds; before teaching it, open the site's Check your school page once on a student device at school. music.csv appears in each student's Files tab by itself (the Files tab can put the lesson's copy back, or add a CSV from the computer). csv.DictReader(f) reads the first line as column names and makes every other line a dictionary; list(...) keeps them all. Every value is text, so "2013" + "1" is "20131" (the Predict) and comparing a year with a number fails (the bug task) until int() changes it. Dictionaries are introduced here only as far as reading one (song["title"]: a value looked up by its key); Deeper Python goes further. with open(...) is a recipe here (copy the lines), taught properly in Deeper Python's Save the game.
The bug task and the first Modify: realising every value is text. Ask students to print one value with type() and predict before fixing.
| What you will see | A question to ask | The fix |
|---|---|---|
| TypeError: '>=' not supported between instances of 'str' and 'int'. | Is the year text or a number at this point? | int(song["year"]) >= 2010. |
| KeyError: 'Genre'. | How is the key spelled in the first line of the file? | Keys must match exactly, including capitals: genre, not Genre. |
| The count prints once for every song. | Is the print indented inside the loop? | Move the print to after the loop, not indented. |
| FileNotFoundError: music.csv. | Is music.csv in the Files tab? | Use "Get this lesson's files again" in the Files tab. |
One possible solution for each task. Other correct programs are fine.
import csv
with open("music.csv") as f:
songs = list(csv.DictReader(f))
print(str(len(songs)) + " songs")
print(songs[0])
for song in songs:
if int(song["year"]) >= 2010:
print(song["title"] + " by " + song["artist"])
import csv
with open("music.csv") as f:
songs = list(csv.DictReader(f))
count = 0
for song in songs:
if song["genre"] == "pop":
count = count + 1
print(str(count) + " pop songs")
import csv
with open("music.csv") as f:
songs = list(csv.DictReader(f))
genre = input("Which genre? ").strip()
count = 0
for song in songs:
if song["genre"].lower() == genre.lower():
print(song["title"] + " (" + song["year"] + ")")
count = count + 1
print(str(count) + " " + genre + " songs")
Stretch: Ask for a year as well, and list only that genre's songs from that year on.
Support: Give students the loop with the if already written, and ask them only to add the count.
Why does int(song["year"]) need int()?
Every value read from a CSV is text; int() turns "2013" into the number 2013 so it can be compared or added.
Next lesson: totals, averages and the longest song. Swapping in another CSV with the same idea (a class survey, sports results) keeps every program working with new keys.