Короткий ответ
Без явного timeout запрос через requests может ждать ответа неограниченно долго, если внешний сервис завис или сеть деградировала, что приводит к зависанию обрабатывающего потока/воркера и, при повторении у многих запросов, к исчерпанию ресурсов приложения.
Как это работает подробнее
По умолчанию у requests нет таймаута на соединение и чтение ответа, поэтому запрос физически может висеть до разрыва соединения операционной системой, что происходит далеко не сразу и не гарантированно.
Пример кода
example.py
import requests
try:
response = requests.get(
"https://external-service.example.com/api",
timeout=(3, 10), # 3с на коннект, 10с на чтение ответа
)
response.raise_for_status()
except requests.exceptions.Timeout:
logger.warning("external service timed out")
raiseЧто использовать на практике
- Практика. Timeout стоит задавать явно и раздельно для connect и read (
timeout=(3, 10)), а поведение при истечении таймаута — оборачивать в обработку исключения requests.Timeout и, при необходимости, повторные попытки с ограниченным числом ретраев и экспоненциальной задержкой.
Подводные камни
- Риск. Ставят один общий большой timeout «на всякий случай», из-за чего пользователь долго ждёт ответа при деградации внешнего сервиса; не обрабатывают исключение таймаута отдельно от прочих сетевых ошибок, из-за чего сложно диагностировать причину сбоя.