My team and I (newbies to python) have written the following code to generate spotify songs related to a specific city and related terms. If the user inputs a city that is not in our CITY_KEY_WORDS list, then it tells the user that the input will be added to a requests file, and then writes the input to a file. The code is as follows:
from random import shuffle
from typing import Any, Dict, List
import spotipy
from spotipy.oauth2 import SpotifyClientCredentials
sp = spotipy.Spotify(
auth_manager=SpotifyClientCredentials(client_id="",
client_secret="")
)
CITY_KEY_WORDS = {
'london': ['big ben', 'fuse'],
'paris': ['eiffel tower', 'notre dame', 'louvre'],
'manhattan': ['new york', 'new york city', 'nyc', 'empire state', 'wall street', ],
'rome': ['colosseum', 'roma', 'spanish steps', 'pantheon', 'sistine chapel', 'vatican'],
'berlin': ['berghain', 'berlin wall'],
}
def main(city: str, num_songs: int) -> List[Dict[str, Any]]:
if city in CITY_KEY_WORDS:
"""Searches Spotify for songs that are about `city`. Returns at most `num_songs` tracks."""
results = []
# Search for songs that have `city` in the title
results += sp.search(city, limit=50)['tracks']['items'] # 50 is the maximum Spotify's API allows
# Search for songs that have key words associated with `city`
if city.lower() in CITY_KEY_WORDS.keys():
for related_term in CITY_KEY_WORDS[city.lower()]:
results += sp.search(related_term, limit=50)['tracks']['items']
# Shuffle the results so that they are not ordered by key word and return at most `num_songs`
shuffle(results)
return results[: num_songs]
else:
print("Unfortunately, this city is not yet in our system. We will add it to our requests file.")
with open('requests.txt', 'r') as text_file:
request = text_file.read()
request = request + city + '\n'
with open('requests.txt', 'w+') as text_file:
text_file.write(request)
def display_tracks(tracks: List[Dict[str, Any]]) -> None:
"""Prints the name, artist and URL of each track in `tracks`"""
for num, track in enumerate(tracks):
# Print the relevant details
print(f"{num + 1}. {track['name']} - {track['artists'][0]['name']} {track['external_urls']['spotify']}")
if __name__ == '__main__':
city = input("Virtual holiday city? ")
number_of_songs = input("How many songs would you like? ")
tracks = main(city, int(number_of_songs))
display_tracks(tracks)
The code runs fine for the "if" statement (if someone enters a city we have listed). But when the else statement is run, 2 errors come up after the actions have been executed ok (it prints and writes the user's input into a file).
The errors that come up are:
Traceback (most recent call last):
File "...", line 48, in <module>
display_tracks(tracks)
File "...", line 41, in display_tracks
for num, track in enumerate(tracks):
TypeError: 'NoneType' object is not iterable
Please excuse my lack of knowledge, but please could someone help with this issue?
We would also like to create a playlist of the songs at the end, however have been facing difficulties with this.
Your
main
function does not have areturn
statement in theelse
clause and that causestracks
to beNone
. Iterating ontracks
when it'sNone
is what's causing the error. There are a few things you can do to improve the code:main
function is doing two different things, checking the input and fetching the tracks..lower()
once in the beginning so you don't have to repeat it.see below the changes I suggested above: