Ошибки и повторы
Сеть ненадёжна: сервер может долго думать, оборвать соединение, ответить ошибкой или попросить «не так часто». Хорошая программа на это рассчитана.
Всегда timeout
r = requests.get(url, timeout=5) # 5 секунд на соединение и на ответ
r = requests.get(url, timeout=(3, 30)) # 3 на соединение, 30 на ответ (большой файл)
Без timeout requests ждёт вечно: программа повиснет, если сервер принял соединение и замолчал.
Исключения requests
Все ошибки requests — наследники requests.RequestException:
| Исключение | Когда |
|---|---|
requests.Timeout (ConnectTimeout, ReadTimeout) |
не дождались соединения или ответа |
requests.ConnectionError |
нет сети, сайт не найден, соединение оборвалось |
requests.HTTPError |
бросает r.raise_for_status() при коде 400 и больше |
requests.JSONDecodeError |
r.json() — тело не JSON (это и ValueError) |
try:
r = requests.get(url, timeout=5)
r.raise_for_status()
data = r.json()
except requests.Timeout:
print("Сервер не ответил вовремя")
except requests.ConnectionError:
print("Нет связи с сервером")
except requests.HTTPError:
print("Ошибка", r.status_code)
except ValueError:
print("Ответ не в формате JSON")
Ловите конкретные исключения — так можно ответить пользователю по делу. except Exception прячет и ваши собственные ошибки в коде.
Проверки по порядку
Сначала код ответа, потом разбор тела: страница ошибки 404 часто приходит в HTML, и r.json() на ней упадёт, хотя настоящая причина — «не найдено». А после разбора проверьте, что пришло то, что вы ждёте: JSON может оказаться списком вместо объекта или не содержать нужного поля.
Повторы
Некоторые ошибки временные — их стоит повторить:
| Код | Повторять? |
|---|---|
| 500, 502, 503, 504 | да, с растущей паузой |
| 429 Too Many Requests | да, после паузы из Retry-After |
| 400, 401, 403, 404 | нет: повтор даст то же самое |
Растущая пауза (экспоненциальная) — 1, 2, 4, 8 секунд: не мучаем упавший сервер частыми запросами. Заголовок Retry-After — прямое указание сервера, сколько ждать:
delay = int(r.headers.get("Retry-After", 1))
time.sleep(delay)
Ограничивайте число попыток и не ждите после последней — дальше всё равно никто не спросит.
В больших программах повторы настраивают один раз — через HTTPAdapter с urllib3.Retry у сессии. Но полезно один раз написать их руками и понимать, что происходит.
Итог
timeoutв каждом запросе;Timeout,ConnectionError,HTTPError— ловим по отдельности;- порядок: код → JSON → нужные поля;
- повторяем только 5xx и 429, паузы растут,
Retry-Afterслушаем.