- Use
list_music_files()to get a list of filenames from the SD card - Use string methods (
rfind, slicing,strip) to extract information from a string - Write a function that takes a filename and returns the song title and artist
- Use a
forloop to process every file automatically - Populate the song list entirely from the SD card β no more typing songs by hand!
In Lesson 1 you created Track objects by hand and called add_track() for each one.
That works, but what if the SD card has 50 songs? You would need 50 lines of code just for setup!
This lesson shows you how to do all of that automatically.
Part 1 β Listing the files on the SD card
The pypod module provides a helper called list_music_files().
Call it and it returns a Python list of filenames β one for every .mp3 file
on the SD card:
from pypod import list_music_files
files = list_music_files()
print(files)
# Example output:
# ['Bohemian Rhapsody (Queen).mp3',
# 'Never Gonna Give You Up (Rick Astley).mp3',
# 'Wonderwall (Oasis).mp3']
Under the hood this uses a standard Python function called os.listdir() β
you will see that in later projects. For now, list_music_files() is all you need.
Part 2 β Taking a filename apart
Every filename follows the same pattern: Song Title (Artist).mp3.
We need to pull it apart to get the title and artist separately.
Let's look at the pieces step by step:
-
Remove the
.mp3extension. A string is a sequence of characters. We can take a slice of it using square brackets:filename[:-4]means "everything except the last 4 characters".filename = "Wonderwall (Oasis).mp3" stem = filename[:-4] # "Wonderwall (Oasis)" -
Find the opening bracket.
rfind("(")searches the string from right to left and returns the position (index) of the last(.position = stem.rfind("(") # 11 (in "Wonderwall (Oasis)") -
Slice the string at that position.
Everything before the bracket is the title; everything
between the brackets is the artist.
title = stem[:position].strip() # "Wonderwall" artist = stem[position + 1 : -1].strip() # "Oasis"πstem[position + 1 : -1]skips the(at the start and the)at the end.strip()removes any extra spaces at the edges.
Part 3 β Putting it in a function
You are going to do the same steps for every filename. Any time you need to repeat the same set of steps, a function is the right tool. Write the logic once; call it as many times as you need.
A function that takes a filename and returns both the title and the artist as a pair (called a tuple) looks like this:
def parse_filename(filename):
"""Given a filename like 'Wonderwall (Oasis).mp3',
return ('Wonderwall', 'Oasis')."""
stem = filename[:-4]
position = stem.rfind("(")
title = stem[:position].strip()
artist = stem[position + 1 : -1].strip()
return title, artist # returning two values at once
# Using the function:
t, a = parse_filename("Wonderwall (Oasis).mp3")
print(t) # Wonderwall
print(a) # Oasis
return title, artist packages both values into a tuple.
On the receiving end, writing t, a = parse_filename(...)
unpacks them automatically β t gets the title, a gets the artist.
This is called tuple unpacking.
Part 4 β Looping over all filenames
A for loop lets you run a block of code once for every item in a list.
Combine that with your new function and you can process every file automatically:
files = list_music_files()
for filename in files:
print(filename) # runs once per filename in the list
Part 5 β Building and displaying the full track list
Now put it all together. For each filename: parse it, create a Track,
and call add_track():
from pypod import Track, add_track, list_music_files, music_path, start
def parse_filename(filename):
"""Return (title, artist) from a filename like 'Song (Artist).mp3'."""
stem = filename[:-4]
position = stem.rfind("(")
title = stem[:position].strip()
artist = stem[position + 1 : -1].strip()
return title, artist
for filename in list_music_files():
title, artist = parse_filename(filename)
track = Track(
title = title,
artist = artist,
file_path = music_path(filename),
)
add_track(track)
start()
- Add the
parse_filenamefunction to yourmain.py. - Replace your hand-written tracks from Lesson 1 with the
forloop above. - Run the code β the player should now list every
.mp3file from the SD card automatically. - Try adding a new MP3 to the SD card (ask your teacher to copy one on), then restart the device. Does it appear without you changing any code?
-
Print the total number of songs found. Hint:
len()returns the length of a list. You will need to store the list of filenames in a variable before theforloop. -
What happens if a filename does not contain brackets?
Can you add a check to your
parse_filenamefunction to handle this gracefully β e.g. use the full stem as the title and leave the artist blank?