Сценарий : мне нужно собрать разбитые на страницы данные из API веб-приложения, для которого ограничение вызовов составляет 100 в минуту. Объект API, который мне нужно вернуть, содержит 100 элементов на страницу, всего 105 и растущие страницы (всего ~ 10500 элементов). Синхронный код занимал приблизительно 15 минут для извлечения всех страниц, поэтому тогда не было никакого беспокойства о превышении пределов вызовов. Однако я хотел ускорить извлечение данных, поэтому я реализовал асинхронные вызовы, используя asyncio
и aiohttp
. Данные теперь загружаются за 15 секунд - хорошо.
Проблема : я сейчас достигаю лимита вызовов, таким образом получая 403 ошибки за последние 5 или около того вызовов.
Предлагаемое решение Я реализовал try/except
, найденный в функции get_data()
. Я выполняю вызовы, а затем, когда вызов не был успешным из-за 403: Exceeded call limit
, я возвращаюсь на back_off
секунд и повторяю до retries
раз:
async def get_data(session, url):
retries = 3
back_off = 60 # seconds to try again
for _ in range(retries):
try:
async with session.get(url, headers=headers) as response:
if response.status != 200:
response.raise_for_status()
print(retries, response.status, url)
return await response.json()
except aiohttp.client_exceptions.ClientResponseError as e:
retries -= 1
await asyncio.sleep(back_off)
continue
async def main():
async with aiohttp.ClientSession() as session:
attendee_urls = get_urls('attendee') # returns list of URLs to call asynchronously in get_data()
attendee_data = await asyncio.gather(*[get_data(session, attendee_url) for attendee_url in attendee_urls])
return attendee_data
if __name__ == '__main__':
data = asyncio.run(main())
Вопрос : Как мне ограничить вызовы aiohttp, чтобы они оставались ниже порогового значения 100 вызовов / минут, не делая 403 запроса на возврат? Я пробовал следующие модули, и ни один из них, похоже, ничего не делал: ratelimiter
, ratelimit
и asyncio-throttle
.
Цель : сделать 100 асинхронных c вызовов в минуту, но при необходимости откат и повторная попытка (403: превышен лимит вызовов).