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
mainfunction does not have areturnstatement in theelseclause and that causestracksto beNone. Iterating ontrackswhen it'sNoneis what's causing the error. There are a few things you can do to improve the code:mainfunction 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: