Я пытаюсь ограничить свои вызовы API на основе приведенных ниже предельных ставок. Для этого я пытаюсь использовать ratelimit
из Python.
Я могу использовать ограничение в секунду на основе ограничения скорости, как показано ниже:
from ratelimit import limits, sleep_and_retry
SEC_CALLS = 10
SEC_RATE_LIMIT = 1
@sleep_and_retry
@limits(calls=SEC_CALLS, period=SEC_RATE_LIMIT)
def check_limit_secs():
print(f'sec time: {time.time()}')
return
##Function Code:
for i in ID:
check_limit_secs()
url = 'https://xxxxxx{}'.format(ID)
headers = {
'Accept': 'application/json'
}
response = requests.get(url, headers=headers)
# Check the response status
if response.status_code == 200:
# Do something with the response data (e.g., print it)
print(i)
# print(response.json())
else:
# Print an error message if the request was not successful
print(f"Error: {response.status_code} - {response.text}")
Этот код не позволяет мне обращаться к API через 1 секунду, но я также хочу ограничить его на основе одной минуты и 30 минут.
К вашему сведению: мой код обрабатывает 25 запросов в секунду, а это означает, что через 10 секунд моя предельная ставка будет достигнута. Это означает, что мой код должен остановиться примерно на 50 секунд, чтобы полностью заполнить лимит в минуту.
Нужно ли мне совершать несколько звонков, используя ratelimit
?
Проблемы:
Одноуровневое ограничение скорости или ограничение скорости: ваша текущая реализация с @limits(calls=SEC_CALLS, period=SEC_RATE_LIMIT)
ограничивает только количество запросов в секунду. Если вы делаете непрерывные запросы, вы можете превысить минутные и получасовые ограничения.
Возможно, происходит накопление запросов: например, в вашем случае вы отправляете 25 запросов в секунду, вы достигнете предела в минуту (250 запросов) через 10 секунд или меньше.
Текущая настройка не остановит дальнейшие запросы при достижении этого ограничения, поэтому вы рискуете превысить минутные или 30-минутные ограничения без дополнительных проверок.
Возможное решение:
Попробуйте одновременно установить несколько ограничений скорости. Вам необходимо учитывать лимиты в секунду, в минуту или в 30 минут.
Возможным решением было бы объединить несколько декораторов @limits
или использовать собственную логику для отслеживания запросов в разных временных окнах.
Но как бы это отследить, довольно утомительно...
например
@sleep_and_retry
@limits(calls=HOUR_CALLS, period=HOUR_RATE_LIMIT)
@sleep_and_retry
@limits(calls=MIN_CALLS, period=MIN_RATE_LIMIT)
@sleep_and_retry
@limits(calls=SEC_CALLS, period=SEC_RATE_LIMIT)
def check_limit():
print(f'Time: {time.time()}'
ИЛИ
В качестве альтернативы вместо этого используйте tenacity
только потому, что он реализует вышеупомянутые проблемы.
Я упоминал ранее...
Например:
from tenacity import retry, stop_after_attempt, wait_random_exponential
@retry(
reraise=True,
wait=wait_random_exponential(min=0.1, max=10),
stop=stop_after_attempt(3),
)
def check_limit(...):
.... your code
@pylearner Привет, это пример, это зависит исключительно от вас, это как способ сказать, не слышу ли я (ваша функция) остановки API. Надеюсь, это поможет?
Привет @Derek Roberts, спасибо за информацию. Это очень полезно и понятно.
Не беспокойтесь... рад, что смог помочь :)
stop=stop_after_attempt(3)
почему я должен использовать здесь 3? или это просто образец, который вы предоставляете?