I'm writing a python script to iterate through new music editorial playlists with the spotify api to pull track, artist, album information into a csv file. My script worked great for a while, perfectly executing through all tracks on the playlists in my list of ids, but stopped while processing a track after about an hour of run-time. I thought this might have to do with my access token expiring, so I added some code towards the beginning of my script to get the cached access token info and refresh it each new run thinking this would re-initiate at least a new hour of run-time so I could dive deeper to see if/where I need to add an automatic refresh while the data pulling is iterating if my access token expires in the future. For whatever reason my script isn't retrieving a bad request or token expire error to the console it is simply just getting stuck while processing the first track on the first playlist as you can see in the screenshot below. For context, while it was working the console was printing every track in the same format from all playlist ids in my list and then it got stuck in the middle of a single playlistid as it is now, but now it is getting stuck at the very first track on the first playlist. I am almost certain this is some sort of issue with my access token, I guess my question is why is it getting stuck and not throwing an error, and how can I fix this so it automatically refreshes properly to continue running without exiting execution early. Thanks!
import csv
from datetime import datetime, timedelta
import spotipy
from spotipy.oauth2 import SpotifyOAuth
import time
# Set up credentials and authorization parameters
client_id = 'myclientid'
client_secret = 'myclientsecret'
redirect_uri = 'https://google.com/'
scope = 'playlist-modify-public playlist-modify-private'
username = 'myusername'
# Create Spotipy object using SpotifyOAuth
sp = spotipy.Spotify(
auth_manager=SpotifyOAuth(
client_id=client_id,
client_secret=client_secret,
redirect_uri=redirect_uri,
scope=scope,
username=username
)
)
# Refresh access token **This is what I added after realizing program was getting stuck after about an hour of run-time**
token_info = sp.auth_manager.get_cached_token()
sp.auth_manager.refresh_access_token(token_info['refresh_token'])
print("Refreshing Access Token.")
new_token_info = sp.auth_manager.get_cached_token()
print("Old access token:", token_info['access_token'])
print("New access token:", new_token_info['access_token'])
# Define a list of playlist IDs
playlist_ids = ['37i9dQZF1DX4JAvHpjipBk', '37i9dQZF1DX0XUsuxWHRQd', '37i9dQZF1DXdwmD5Q7Gxah', '37i9dQZF1DXcBWIGoYBM5M', '37i9dQZF1DX10zKzsJ2jva', '37i9dQZF1DWY7IeIP1cdjF', '37i9dQZF1DX76Wlfdnj7AP', '37i9dQZF1DX0FOF1IUWK1W', '37i9dQZF1DX1lVhptIYRda', '37i9dQZF1DXdSjVZQzv2tl', '37i9dQZF1DX4sWSpwq3LiO', '37i9dQZF1DWY4xHQp97fN6', '37i9dQZF1DWZjqjZMudx9T', '37i9dQZF1DX4SBhb3fqCJd', '37i9dQZF1DX4dyzvuaRJ0n', '37i9dQZF1DWTkIwO2HDifB', '37i9dQZF1DWWQRwui0ExPn', '37i9dQZF1DXaXB8fQg7xif', '37i9dQZF1DX5BAPG29mHS8', '37i9dQZF1DWZd79rJ6a7lp', '37i9dQZF1DXcZQSjptOQtk', '37i9dQZF1DXcF6B6QPhFDv', '37i9dQZF1DX9tPFwDMOaN1', '37i9dQZF1DWWY64wDtewQt', '37i9dQZF1DX0BcQWzuB7ZO', '37i9dQZF1DXcZDD7cfEKhW', '37i9dQZF1DWYBO1MoTDhZI', '37i9dQZF1DXbbu94YBG7Ye', '37i9dQZF1DXb0COFso7q0D', '37i9dQZF1DWY4lFlS4Pnso', '37i9dQZF1DWUa8ZRTfalHk', '37i9dQZF1DXaxEKcoCdWHD', '37i9dQZF1DWSpF87bP6JSF', '37i9dQZF1DX6GwdWRQMQpq']
tracksData = []
# Iterate through playlist IDs and extract track information
for playlist_id in playlist_ids:
# Use Spotipy API to get playlist data
playlist = sp.playlist(playlist_id)
# Use Spotipy API to get track data
results = sp.playlist_tracks(playlist_id)
count = 1
# Extract track information and add to tracksData array
for track in results['items']:
track = track['track']
print(f"Processing track: {track['artists'][0]['name']} - {track['name']} from playlist: {playlist['name']}")
start_time = time.time()
try:
sp.artist(track['artists'][0]['id'])
sp.track(track['id'])
sp.album(track['album']['id'])
except:
pass
elapsed_time = time.time() - start_time
if elapsed_time > 3:
print(f"Skipping track: {track['artists'][0]['name']} - {track['name']} from playlist: {playlist['name']} (took too long to process)")
continue
tracksData.append({
'artistName': track['artists'][0]['name'],
'songName': track['name'],
'releaseDate': track['album']['release_date'],
'positionInPlaylist': count,
'artistFollowers': sp.artist(track['artists'][0]['id'])['followers']['total'],
'albumImageUrl': track['album']['images'][0]['url'],
'trackPopularity': track['popularity'],
'artistPopularity': sp.artist(track['artists'][0]['id'])['popularity'],
'isrc': track['external_ids']['isrc'],
'albumLabel': sp.album(track["album"]["id"])["label"],
'albumExternalUrl': track['album']['external_urls']['spotify'],
'playlistId': playlist_id,
'playlistName': playlist['name'], # Set playlistName to actual name of playlist
'playlistImage': playlist['images'][0]['url'], # Add playlist image to dictionary
'playlistFollowers': playlist['followers']['total'], # Add playlist followers to dictionary
'trackId': track['id'], # Add track ID to dictionary
'albumId': track['album']['id'] # Add album ID to dictionary
})
count += 1
time.sleep(2) # Pause for 2 seconds before processing the next playlist
# Calculate the most recent Friday
today = datetime.today()
friday = today - timedelta((today.weekday() - 4) % 7)
# Calculate the date 7 days prior to the most recent Friday
lastWeekFriday = friday - timedelta(days=7)
# Create a list of track dictionaries with release dates within the past week
recentTracks = []
for track in tracksData:
# Convert release date string to datetime object
releaseDate = datetime.strptime(track['releaseDate'], '%Y-%m-%d')
# Check if release date is within the past week
if lastWeekFriday <= releaseDate < friday:
recentTracks.append(track)
# Create and write track data to CSV file
with open('tracksData.csv', mode='w', newline='') as csv_file:
fieldnames = ['artistName', 'songName', 'releaseDate', 'positionInPlaylist', 'artistFollowers', 'albumImageUrl',
'trackPopularity', 'artistPopularity', 'isrc', 'albumLabel', 'albumExternalUrl', 'playlistId',
'playlistName', 'playlistImage', 'playlistFollowers', 'trackId', 'albumId']
writer = csv.DictWriter(csv_file, fieldnames=fieldnames)
writer.writeheader()
for track in recentTracks:
writer.writerow(track)
Edit: I just tried switching auth methods to client flow since I'm not using any user scopes really in my code to see if it would make a difference. The new auth method has been incorporated into the 2nd block of code. It has not changed anything, it is still stuck. New attempt fixing using client auth method. Tried adding refresh before iterating thru playlists too and also try except argument during iterations, still stuck processing 1st track.
client_id = 'client_id'
client_secret = 'client_secret'
auth_manager = SpotifyClientCredentials(client_id=client_id, client_secret=client_secret)
sp = spotipy.Spotify(auth_manager=auth_manager)
...
def refresh_access_token():
sp.auth_manager.get_access_token(as_dict=False, check_cache=False)
refresh_access_token()
# Iterate through playlist IDs and extract track information
for playlist_id in playlist_ids:
# Use Spotipy API to get playlist data
playlist = sp.playlist(playlist_id)
# Use Spotipy API to get track data
results = sp.playlist_tracks(playlist_id)
count = 1
# Extract track information and add to tracksData array
for track in results['items']:
track = track['track']
print(f"Processing track: {track['artists'][0]['name']} - {track['name']} from playlist: {playlist['name']}")
start_time = time.time()
while True:
try:
tracksData.append({
'artistName': track['artists'][0]['name'],
'songName': track['name'],
'releaseDate': track['album']['release_date'],
'positionInPlaylist': count,
'artistFollowers': sp.artist(track['artists'][0]['id'])['followers']['total'],
'albumImageUrl': track['album']['images'][0]['url'],
'trackPopularity': track['popularity'],
'artistPopularity': sp.artist(track['artists'][0]['id'])['popularity'],
'isrc': track['external_ids']['isrc'],
'albumLabel': sp.album(track["album"]["id"])["label"],
'albumExternalUrl': track['album']['external_urls']['spotify'],
'playlistId': playlist_id,
'playlistName': playlist['name'], # Set playlistName to actual name of playlist
'playlistImage': playlist['images'][0]['url'], # Add playlist image to dictionary
'playlistFollowers': playlist['followers']['total'], # Add playlist followers to dictionary
'trackId': track['id'], # Add track ID to dictionary
'albumId': track['album']['id'] # Add album ID to dictionary
})
count += 1
break
except spotipy.exceptions.SpotifyException:
refresh_access_token()
except Exception as e:
print(e)
time.sleep(2) # Pause for 2 seconds before processing the next playlist