#Что произошло и когда проявляется ошибка
В Python вызов сетевой библиотеки без ограничения ожидания может казаться зависшим, когда сервер не отвечает или медленно передаёт данные: нужны отдельные тайм-ауты подключения и чтения, диагностический журнал и обработка исключений.
#Причины и диагностические признаки
| Возможная причина | Как узнать | Что делать |
|---|---|---|
| Нет ограничения ожиданияRequests по умолчанию не задаёт тайм-аут. | requests.get(url) без timeout висит на ненадёжном сервере | Передать timeout=(connect, read). |
| Сервер медленно отдаёт ответТайм-аут чтения контролирует паузы без поступления данных, не всю длительность загрузки. | Зависание уже после установления соединения | Проверить размер и потоковую обработку. |
| Сетевой посредник мешаетПрокси, DNS или блокировка соединений меняют поведение запроса. | Один адрес висит только из офисной сети | Сравнить разрешённый запрос из другой известной среды. |
#Подробная пошаговая диагностика и исправление
- 1. Определите место ожиданияВ тестовой копии добавьте вывод времени до запроса и после него. Если второй вывод отсутствует, проверьте, создаётся ли соединение и не выполняется ли другое блокирующее действие. Не выводите в журнал полный URL с токеном и секретными параметрами.
- Пример кода по темеPythonОбразец кода для файла .py в тестовой копии проекта; перед внедрением замените имена файлов на реальные.
from datetime import datetime print("Начало:", datetime.now().isoformat()) # здесь ваш запрос print("Конец:", datetime.now().isoformat())
- 2. Добавьте два тайм-аута в RequestsВыполняйте только разрешённые запросы. Для небольшого ответа задайте
timeout=(5, 20): до 5 секунд ожидания подключения и 20 секунд ожидания без очередного блока данных. Значения подберите к требованиям сервиса. Этот параметр не ограничивает суммарное время загрузки ответа. - Пример кода по темеPythonОбразец кода для файла .py в тестовой копии проекта; перед внедрением замените имена файлов на реальные.
import requests r = requests.get("https://www.python.org/", timeout=(5, 20)) r.raise_for_status() print(r.status_code, len(r.content))
- 3. Различайте сетевые ошибкиОбработайте
requests.exceptions.Timeoutотдельно от ошибок TLS, соединения и HTTP. Повторяйте запросы с паузой только если они идемпотентны, например чтение GET; повтор POST с оплатой или созданием объекта может продублировать действие. - Пример кода по темеPythonОбразец кода для файла .py в тестовой копии проекта; перед внедрением замените имена файлов на реальные.
import requests try: r = requests.get("https://www.python.org/", timeout=(5, 20)) r.raise_for_status() except requests.exceptions.Timeout: print("Истекло время ожидания") except requests.exceptions.RequestException as exc: print("Сбой запроса:", type(exc).__name__)
- 4. Проверьте обработку больших ответовЕсли сервер отдаёт много данных, не сохраняйте полный ответ в оперативную память без необходимости. Для больших ответов применяйте потоковую обработку (
stream=Trueиiter_content) с закрытием ответа; ограничьте максимальный размер и учитывайте, что тайм-аут на чтение — не общий лимит выполнения.
- 5. Проверьте работу при искусственном сбоеВ отдельной проверке используйте контролируемый тестовый сервер, который задерживает ответ, и убедитесь, что запрос завершится предсказуемой ошибкой, а приложение сообщит пользователю о проблеме. Не проверяйте сбой на случайных чужих сайтах многократными запросами.
#Как проверить, что проблема устранена
В нормальной сети запрос возвращает ответ; при задержке более установленных ограничений приложение обрабатывает Timeout и не остаётся бесконечно заблокированным.
#Если исправление не помогло
Если требуется строгое ограничение общей длительности работы, вводите его отдельно на уровне выполнения задачи: стандартный timeout Requests контролирует отдельные периоды ожидания.