简体   繁体   English

urllib3:抛出 MaxRetryError 时如何获得响应?

[英]urllib3: How to get response when MaxRetryError is thrown?

I'm using the Retry module from Python urllib3 + requests for a case where a 3rd party API gives sporadic errors.我正在使用来自 Python urllib3的重试模块 + requests第 3 方 API 给出零星错误的情况。 One issue I have is that if the retries keep failing, I get a exceptions.MaxRetryError and never get to see what the response was.我遇到的一个问题是,如果重试一直失败,我会得到一个exceptions.MaxRetryError并且永远看不到响应是什么。 What if there was valuable debugging data coming from the server?如果有来自服务器的有价值的调试数据怎么办?

Is there a way to still get the response in cases that would throw MaxRetryError ?有没有办法在抛出MaxRetryError的情况下仍然获得响应?

Here's my code below下面是我的代码

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")

First, I would like to mention that from requests.packages.urllib3.util.retry import Retry is no longer needed since urllib3 has been unvendored from requests.首先,我想提一下from requests.packages.urllib3.util.retry import Retry不再需要,因为 urllib3 已从请求中取消供应。 Consider using the from urllib3.util.retry import Retry form instead as it does not involve hacks (see https://github.com/psf/requests/blob/v2.22.0/requests/packages.py ).考虑使用from urllib3.util.retry import Retry表单,因为它不涉及黑客攻击(请参阅https://github.com/psf/requests/blob/v2.22.0/requests/packages.py )。

You can't get both the MaxRetryError and the response from urllib3.您无法同时获得MaxRetryError和来自 urllib3 的响应。 But you can get the response from urllib3, and use raise_for_status at the requests level.但是您可以从 urllib3 获得响应,并在请求级别使用raise_for_status However, raise_for_status() won't be affected by your status_forcelist , so you may want to reimplement it yourself.但是, raise_for_status()不会受到您的status_forcelist的影响,因此您可能需要自己重新实现它。

Here's an adaption of your code that 1/ retries on statuses 2/ prints the final response 3/ raises an exception.这是您的代码的改编版,它 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()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM