Я работаю над проектом, использующим Spotipy, который делает много запросов. Примерно 18 часов назад я предполагаю, что достиг предела скорости, потому что отправлял много запросов, и код начал просто останавливаться и зависать навсегда, как только он дошел до строки, содержащей ссылку на API. После этого я сдался и пошел спать. ~ 12 часов назад я решил переписать весь проект, так как он был беспорядочным, и поэтому я мог реализовать интервал между запросами API. Я также узнал, что могу установить retries = 0, чтобы он выдавал ошибку, а не зависал на неопределенный срок. Я переписывал проект, мне удалось сделать только 1 запрос к API, прежде чем я начал каждый раз получать http 429 ошибки. Я оставил его в покое еще на пару часов, пока не попытался устранить неполадки еще раз, и произошло то же самое: мне удалось добиться одного успеха, а затем возникли ошибки.
restart.py:
import spotipy # type: ignore
from spotipy.oauth2 import SpotifyOAuth # type: ignore
import time
def create_client() -> spotipy.Spotify:
sp: spotipy.Spotify = spotipy.Spotify(
retries=0,
auth_manager=SpotifyOAuth(
client_id='my_id',
client_secret='_my_secret',
scope='playlist-read-private playlist-modify-public playlist-modify-private',
redirect_uri='http://localhost:8888/callback'
)
)
return sp
class APIRequests:
def __init__(self, user_id: str) -> None:
self.recent_request: float = time.time()
self.sp: spotipy.Spotify = create_client()
self.user_id: str = user_id
def get_playlist_tracks(self, playlist: str, offset: int, retries: int=0):
delta_time = time.time() - self.recent_request
if delta_time > 1:
try:
return self.sp.user_playlist_tracks(self.user_id, playlist, offset=offset, limit=100)
except spotipy.exceptions.SpotifyException as e:
if e.http_status == 429:
print(e)
print(e.headers.get('retry-after'))
print(f'retrying: waiting {(2 ** retries) * 4} seconds...')
time.sleep((2 ** retries) * 4)
retries += 1
return self.get_playlist_tracks(playlist, offset, retries)
else:
raise e
else:
time.sleep(1 - delta_time)
self.get_playlist_tracks(playlist, offset)
api_client: APIRequests = APIRequests('my_user_id')
def get_playlist_tracks(playlist: str) -> list:
offset: int = 0
tracks: list = []
while True:
print('sending request ...')
request_batch = api_client.get_playlist_tracks(playlist, offset)
print('request recieved')
for track in request_batch['items']:
tracks.append(track['track'])
if not request_batch["next"]:
break
return tracks
if __name__ == '__main__':
tracks = get_playlist_tracks('my_playlist')
print(len(tracks))
В моем переписанном коде все запросы разделены как минимум 1 секундой (хотя это даже не имеет значения, потому что я все равно не могу пройти мимо 1 запроса). Кроме того, после получения ошибки http 429 он будет ждать экспоненциально увеличивающееся время, прежде чем повторить попытку. Это не имеет никакого эффекта. Я запускал его до тех пор, пока между попытками не прошло 2 минуты, но ошибка все равно выдавалась.
Что для меня не имеет смысла, так это то, что ограничение скорости применяется только к количеству запросов, сделанных в любом 30-секундном окне. Если я подожду до 2 минут, проблем не должно возникнуть. Если бы я получал только ошибку, я бы предположил, что у меня какой-то 24-часовой запрет API или что-то в этом роде, но возможность сделать 1 успешный запрос не имеет смысла.
Я попробовал использовать идентификатор/секрет клиента для обоих двух приложений, которые есть в моей учетной записи разработчика Spotify, и у меня возникла та же проблема.
Правильно ли я подхожу к этому? Есть ли у меня проблема в моем коде? Любая помощь приветствуется.
Кроме того:
Если ваше приложение ограничено по скорости, оно получит ответ об ошибке 429 от Spotify. Ваше приложение может использовать эту информацию как сигнал для замедления количества запросов API, которые оно отправляет к веб-API. Заголовок ответа 429 обычно включает заголовок Retry-After со значением в секундах. Рассмотрите возможность ожидания количества секунд, указанного в Retry-After, прежде чем ваше приложение снова вызовет веб-API.
Я не вижу ничего подобного в сообщении об ошибке. Как я могу получить доступ к повторной попытке и решит ли это мою проблему?
Я не знаю ограничений в Spotify, но в других API часто есть ограничение на 1-минутное окно и дневной лимит, а иногда и месячный лимит.
@furas Как мне получить доступ к retry-after? Или как мне получить доступ к заголовкам? [developer.spotify.com/documentation/web-api/concepts/… документация по пределу скорости) не упоминает ничего, кроме 30-секундного окна.
Прошло уже почти 24 часа, как все перестало работать, и теперь все снова работает. Должен ли я ответить на свой вопрос и сказать, что все выяснилось само собой? Стоит ли мне удалить свой вопрос? (Извините, я новичок на сайте)
Вы могли бы ответить на свой вопрос. Эта информация может быть полезна — особенно потому, что вы не нашли эту информацию в официальной документации.






Прочитав сообщение об ошибке более внимательно, я обнаружил, что у меня истекло время ожидания из-за слишком большого количества раз превышения предела скорости. В тот раз мой тайм-аут длился чуть меньше 24 часов. Единственное решение – ждать.
Я предполагаю, что чем меньше вы пытаетесь отправить запросы во время тайм-аута, тем он короче, поскольку еще два раза, когда у меня был тайм-аут с тех пор, как я задал вопрос, были намного короче, чем первый, и я не проверял, чтобы увидеть если бы у меня не было тайм-аута так же, как в первый раз.
Что касается того, чтобы избежать тайм-аута, я не уверен. Даже если я ограничил количество запросов до 1 в секунду, тайм-аут у меня все равно был еще дважды, но я также отправлял запросы без перерыва более часа, когда у меня вышел тайм-аут.
Чтобы устранить тайм-аут: просто подождите и время от времени проверяйте, можете ли вы снова отправлять запросы. У меня второй раз это длилось около 12 часов.
Чтобы избежать тайм-аута: не отправляйте слишком много запросов одновременно.
в коде вы используете
retry-after, но, возможно, так и должно бытьRetry-After. ИЛИ, возможно, отобразите все заголовки, чтобы увидеть, что вы действительно получаете.