JavaRush /Курсы /Python SELF /Ретрай и таймауты для устойчивости скрипта

Ретрай и таймауты для устойчивости скрипта

Python SELF
34 уровень , 3 лекция
Открыта

1. Обработка ошибок в скриптах

Проблемы веб-скрейпинга

Представьте: ваш скрипт сидит такой весь красивый, готовый к работе, но внезапно поскользнулся на банановой корке — и на тебе! Ошибки и сбои. Как сделать так, чтобы он выживал в суровых условиях Интернета? Сегодня мы с вами обучим его двум важнейшим навыкам: выдержке и повторению попыток. Да-да, мы настроим ретраи и таймауты.

Работа с веб-скрейпингом может быть славной до тех пор, пока вы не обнаружите, что ваш скрипт внезапно отключился благодаря:

  • Сбоям соединения.
  • Временной недоступности серверов.
  • Непредсказуемым изменениям в HTML-структуре страниц.

Ваш скрипт, словно джедай, должен быть готов к неожиданностям и уметь справляться с ними. Иногда проблемы можно решить, просто подождав минутку и повторив запрос. И вот тут на сцену выходят наши герои — ретраи и таймауты!

Введение в механизмы обработки ошибок

Для начала, давайте вспомним основу — обработка ошибок в Python. Мы используем блоки try-except, чтобы управлять ошибками и не давать им загубить работу нашего скрипта.

Python

import requests

try:
    response = requests.get('https://example.com')
    response.raise_for_status()  # проверка успешности запроса
except requests.exceptions.RequestException as e:
    print(f'Произошла ошибка: {e}')

2. Настройка ретраев

Почему стоит использовать повторы попыток?

Скрипт, который просто сдается при первом же сбое, — это как кот, который боится проливного дождя. А вам нужен скрипт, который стойко переживет пару неудобств. Именно поэтому мы настраиваем ретраи — так ваш скрипт станет уверенным в себе.

Как настраивать повторные попытки

Теперь давайте разберемся, как мы можем организовать повторные попытки. Один из самых простых способов — использовать библиотеку urllib3, которая предоставляет функциональность для автоматической повторной отправки запроса при ошибках.

Python

from urllib3.util.retry import Retry
from requests.adapters import HTTPAdapter
import requests

session = requests.Session()
retries = Retry(total=5, backoff_factor=1, status_forcelist=[500, 502, 503, 504])
session.mount('https://', HTTPAdapter(max_retries=retries))

try:
    response = session.get('https://example.com')
    response.raise_for_status()
    print(response.content)
except requests.exceptions.RequestException as e:
    print(f'Произошла ошибка: {e}')

В этом примере мы создали session, к которой применили механизм повторных попыток (Retry). Мы сказали, что стоит сделать до 5 попыток в случае сбоя с кодами 500, 502, 503 и 504. backoff_factor=1 означает, что время между попытками будет увеличиваться по принципу экспоненциального роста (1, 2, 4, 8... секунд).

3. Таймауты: предотвращение зависания

Отложим капризное ожидание

Таймауты — как будильник: помогут не зависнуть в ожидании ответа сервера. Установив таймаут, вы говорите вашему скрипту: "Хватит ждать! Если сервер не ответит за указанное время, двигайся дальше!"

Python

try:
    response = requests.get('https://example.com', timeout=10)
    response.raise_for_status()
    print(response.content)
except requests.exceptions.Timeout:
    print('Запрос превысил время ожидания')
except requests.exceptions.RequestException as e:
    print(f'Произошла ошибка: {e}')

Зачем это нужно?

Вы когда-нибудь застывали в ожидании, пока ваш скрипт не получит ответ от сервера, который уже сгорел как тост? Таймауты предохраняют от ненужного ожидания и дают вашему коду возможность быстро восстановиться и продолжить работу. Не заставляйте ваш скрипт "думать", что он смог бы пару раз сходить на перекур за это время!

4. Примеры настройки

Реализация устойчивого скрипта с применением ретраев

Теперь давайте соберем наш скрипт, который будет устойчив как броня железного человека. Мы будем использовать как таймауты, так и повторы.

Python

from urllib3.util.retry import Retry
from requests.adapters import HTTPAdapter
import requests

def fetch_url(url):
    session = requests.Session()
    retries = Retry(total=5, backoff_factor=1, status_forcelist=[500, 502, 503, 504])
    session.mount('https://', HTTPAdapter(max_retries=retries))

    try:
        response = session.get(url, timeout=10)
        response.raise_for_status()
        return response.content
    except requests.exceptions.Timeout:
        print('Запрос превысил время ожидания')
    except requests.exceptions.RequestException as e:
        print(f'Произошла ошибка: {e}')
    return None

content = fetch_url('https://example.com')
if content:
    print('Успешно скачали данные!')

Использование таймаутов для предотвращения зависания скрипта

Мы уже продемонстрировали, как установить таймауты. Давайте теперь убедимся, что наш скрипт не просто устойчив, но и разумно реагирует на долгое ожидание. Вместо того чтобы "подвиснуть", он просто напомнит об этом хозяину: "Эй, сервер слишком долго думает, я не собираюсь ждать!"

Вот такой простой и лаконичный подход сделает ваш код надежным и готовым к бою с всевозможными непредсказуемыми ситуациями, которые могут возникнуть в Интернете.

Практическое применение

Когда вы разрабатываете реальные проекты по скрейпингу, часто приходится иметь дело с различными ограничениями со стороны серверов. Ретраи и таймауты являются вашими лучшими друзьями для минимизации риска сбоев. Это поможет вам обеспечить бесперебойную работу вашего кода, особенно при автоматизированной обработке данных и в тех случаях, когда важно получать точные результаты в срок. Эти техники также могут повысить качество вашего резюме и уровень доверия клиентов, которым вы предоставляете данные.

Комментарии (1)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Vlad Tagunkov Уровень 29
10 января 2025
😂 вот ведь есть разница для валидатора "Используйте сообщение 'Таймаут истек' вместо 'We have request time out'." без этого сообщения задача не засчиталась 😂