Распараллеливание асинхронных вызовов API в PythonPython

Программы на Python
Ответить
Anonymous
 Распараллеливание асинхронных вызовов API в Python

Сообщение Anonymous »

Я создаю конвейер приема данных на Python, который собирает данные из стороннего REST API.
API допускает максимум 100 запросов в минуту, и мне нужно получать данные для десятков тысяч элементов.
Вот упрощенная версия моего текущего подхода с использованием asyncio и aiohttp:

Код: Выделить всё

import asyncio
import aiohttp

async def fetch(session, url):
async with session.get(url) as resp:
return await resp.json()

async def main(urls):
async with aiohttp.ClientSession() as session:
tasks = [fetch(session, url) for url in urls]
results = await asyncio.gather(*tasks)
return results

urls = [f"https://api.example.com/items/{i}" for i in range(10000)]
data = asyncio.run(main(urls))

Это работает для небольших наборов URL-адресов, но не работает в масштабе — я быстро превышаю ограничение скорости и начинаю получать ошибки HTTP 429.
Я пробовал ввести семафоры и интервалы ожидания:

Код: Выделить всё

semaphore = asyncio.Semaphore(10)

async def fetch_limited(session, url):
async with semaphore:
async with session.get(url) as resp:
if resp.status == 429:
await asyncio.sleep(60)
return await fetch_limited(session, url)
return await resp.json()
Однако:
Это неэффективно — спящие режимы блокируют все задачи, а не только те, которые ограничены по скорости.
У меня все еще иногда возникают всплески 429, вероятно, из-за планирования параллелизма.
Повторные попытки непоследовательны и могут привести к зависанию некоторых задач.
Вопрос:
Каков наиболее эффективный и Pythonic способ:
Асинхронно распараллелить большое количество вызовов API
Соблюдать строгие ограничения скорости (например, 100 запросов в минуту)
Четко обрабатывать повторы и экспоненциальную отсрочку
Избегать блокировки цикла событий при ограничении скорости
Будет использоваться такие библиотеки, как aiolimiter, tenacity или архитектура asyncio.Queue, подходят лучше?
Я ищу надежный шаблон проектирования или пример, который изящно масштабируется, не нарушая ограничений скорости.

Подробнее здесь: https://stackoverflow.com/questions/798 ... -in-python
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Python»