Есть ли способ глобально переопределить тайм-аут запросов?
У нас есть утилиты библиотеки запросов, замусоренной по всему нашему проекту. Недавно мы столкнулись с ошибкой в одном из наших пунктов назначения, где он заморозил среднюю транзакцию и решил просто закрыть соединение.
Естественно, наше приложение последовали этому примеру.
Есть ли переменная среды или какой-либо другой способ установить тайм-аут? Даже если это значительное (скажем, 30 секунд), этого должно быть достаточно, чтобы остановить все работы от остановки из-за одной службы. Если это возможно, оно должно быть глобальным, чтобы мне не приходилось находить каждое его использование, и чтобы люди не могли забыть добавить его в будущем.
Ответы
Ответ 1
К сожалению, глядя на код, нет возможности установить глобальное значение по умолчанию. Я был немного удивлен этим, так как ожидал, что это будет довольно распространенный случай. Если вы запустите запрос на добавление функции, сообщите мне об этом (например, в комментариях к этому сообщению).
Причина этого заключается в том, что такие методы, как get(...)
, post(...)
и т.д., Являются всего лишь тонкими обертками над методом Session.request(...)
(requests.get(...)
создает новый однократный сеанс только для одного запроса). Этот метод принимает timeout
в качестве аргумента и не проверяет внутренности Session
на наличие значения, если нет аргумента тайм-аута, поэтому вы всегда должны помещать его туда вручную, как 2ps, предложенное в его ответ.
Источники:
requests/__init__.py
- импортировать API в область действия пакета, чтобы предоставить утилиты requests.get(...)
-like
requests.api
- модуль API, импортированный в пункт выше; использовать сеансы с одним выстрелом
requests.sessions
- Session
реализация
PS. See this pull request. Disclaimer: it mine.
Ответ 2
Два способа сделать это. Это связано с некоторыми грязными патчами обезьян. Протестировано на python 3.6.
Поместите это где-нибудь в файл, например main.py, init.py или urls.py и убедитесь, что он вызывается.
Вариант 1: исправить метод запросов
import requests
def request_patch(slf, *args, **kwargs):
print("Fix called")
timeout = kwargs.pop('timeout', 2)
return slf.request_orig(*args, **kwargs, timeout=timeout)
setattr(requests.sessions.Session, 'request_orig', requests.sessions.Session.request)
requests.sessions.Session.request = request_patch
Вариант 2: Запустите класс Session
import requests
class SessionTimeoutFix(requests.Session):
def request(self, *args, **kwargs):
print("Fix called")
timeout = kwargs.pop('timeout', 2)
return super().request(*args, **kwargs, timeout=timeout)
requests.sessions.Session = SessionTimeoutFix
Ответ 3
Вместо этого вы можете унаследовать класс request.Session и переписать функцию request
, например, так:
HTTP_TIMEOUT = 30
class TimeoutRequestsSession(requests.Session):
def request(self, *args, **kwargs):
kwargs.setdefault('timeout', HTTP_TIMEOUT)
return super(TimeoutRequestsSession, self).request(*args, **kwargs)
session = TimeoutRequestsSession()
session.get('https://www.google.com') # connection timeout is default 30s
Ответ 4
Вы можете сделать это за один вызов с помощью параметра timeout
:
requests.get('http://www.google.com', timeout=10)
Параметр timeout
указывает количество секунд или кортеж (время ожидания подключения, тайм-аут чтения). Вы можете больше узнать об этом здесь.
Если вы хотите сделать этот глобальный, самый простой способ - реорганизовать все вызовы в класс-оболочку и убедиться, что каждый использует класс-оболочку для вызова этой конечной точки API. Я быстро проверил код запросов и не видел использования глобального переопределения для таймаута, поскольку поведение по умолчанию - это ожидание данных.
Ответ 5
Почему нет?:
for method in ("get", "options", "head", "post", "put", "patch", "delete"):
setattr(
session,
method,
functools.partial(getattr(session, method), timeout=timeout),
)