urllib3: Как получить ответ, когда выдается MaxRetryError? - PullRequest
1 голос
/ 06 ноября 2019

Я использую модуль Retry из Python urllib3 + requests для случая, когда сторонний API выдает случайные ошибки. У меня есть одна проблема: если повторные попытки продолжаются неудачно, я получаю exceptions.MaxRetryError и никогда не вижу, каков был ответ. Что, если с сервера поступили ценные отладочные данные?

Есть ли способ получить ответ в случаях, которые выдают MaxRetryError?

Вот мой код ниже

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

def req_with_retry(retries=3, backoff_factor=0.5, status_forcelist=(400, 404, 500, 502, 504,), method_whitelist=frozenset(['POST', 'HEAD', 'TRACE', 'GET', 'PUT', 'OPTIONS', 'DELETE']), session=None,):
    ''' 
    this returns a session that functions like the requests module but with retries built it for certain status codes
    '''
    session = session or requests.Session()
    retry = Retry(
        total=retries,
        read=retries,
        connect=retries,
        backoff_factor=backoff_factor,
        status_forcelist=status_forcelist,
        method_whitelist=method_whitelist
    )
    adapter = HTTPAdapter(max_retries=retry)
    session.mount('http://', adapter)
    session.mount('https://', adapter)
    return session

r = req_with_retry().get(url="https://www.google.com")

1 Ответ

0 голосов
/ 14 ноября 2019

Во-первых, я хотел бы отметить, что from requests.packages.urllib3.util.retry import Retry больше не нужен, так как urllib3 не обрабатывается в запросах. Попробуйте вместо этого использовать форму from urllib3.util.retry import Retry, поскольку она не включает хаки (см. https://github.com/psf/requests/blob/v2.22.0/requests/packages.py).

. Вы не можете получить и , MaxRetryError и ответ от urllib3. Но вы можетеполучите ответ от urllib3 и используйте raise_for_status на уровне запросов. Однако status_forcelist не будет затронут вашим *1011*, поэтому вы можете захотеть переопределить его самостоятельно.

Вот адаптациявашего кода, который 1 / повторяет статусы 2 / печатает окончательный ответ 3 / вызывает исключение.

import logging

import urllib3
import requests
import requests.adapters

logging.basicConfig(level=logging.DEBUG)
logging.getLogger("urllib3").setLevel(logging.DEBUG)


def req_with_retry(
    retries=3,
    backoff_factor=0.5,
    status_forcelist=(400, 404, 500, 502, 504),
    method_whitelist=frozenset(
        ["POST", "HEAD", "TRACE", "GET", "PUT", "OPTIONS", "DELETE"]
    ),
    session=None,
):
    """Returns a session that functions like the requests module but with retries
    built it for certain status codes
    """
    session = session or requests.Session()
    retry = urllib3.Retry(
        total=retries,
        read=retries,
        connect=retries,
        backoff_factor=backoff_factor,
        status_forcelist=status_forcelist,
        method_whitelist=method_whitelist,
        raise_on_status=False,
    )
    adapter = requests.adapters.HTTPAdapter(max_retries=retry)
    session.mount("http://", adapter)
    session.mount("https://", adapter)
    return session


r = req_with_retry().get(url="https://httpbin.org/status/404")
print(r.status_code, r.text)
r.raise_for_status()
...