当Python请求库遇到重试限制时如何访问服务器响应

Bre*_*ier 5 python python-2.7 python-requests

我正在使用Python请求库来实现重试逻辑。这是我制作的一个简单脚本,用于重现我遇到的问题。在重试用完的情况下,我希望能够至少记录服务器的响应之一以帮助调试。但是,我不清楚如何访问该信息。当然,我可以通过其他方式实现重试来实现我的目标,但是似乎这并不是一个极端的情况,而令我惊讶的是,发现请求不支持我的用例。

我已经看过了包装的requests.exceptions.RetryError,包装的requests.packages.urllib3.exceptions.MaxRetryError和包装都没有用的request.packages.urllib3.exceptions.ResponseError。

我想念什么吗?

#!/usr/bin/env python

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


def main():
    retry_policy = Retry(
        total=3,
        status_forcelist=[418])

    session = requests.Session()
    session.mount('http://', HTTPAdapter(max_retries=retry_policy))

    try:
        session.get('http://httpbin.org/status/418')
    except RetryError as retry_error:
        print retry_error
        print retry_error.response is None


if __name__ == '__main__':
    main()
Run Code Online (Sandbox Code Playgroud)

$ python test.py

HTTPConnectionPool(host='httpbin.org', port=80): Max retries exceeded with url: /status/418 (Caused by ResponseError('too many 418 error responses',))

True
Run Code Online (Sandbox Code Playgroud)

Bre*_*ier 8

检出urllib3源,我发现该Retry对象采用名为的命名参数raise_on_statusTrue是默认值。设置False为时,遇到重试限制将导致返回响应,而不是引发异常。下面的代码显示了我使用上的方法导致引发了一个HTTPError(包含Response),但是直接使用它可能同样容易。raise_for_statusResponseResponse

#!/usr/bin/env python

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


def main():
    retry_policy = Retry(
        total=3,
        status_forcelist=[418],
        raise_on_status=False)

    session = requests.Session()
    session.mount('http://', HTTPAdapter(max_retries=retry_policy))

    try:
        response = session.get('http://httpbin.org/status/418')
        response.raise_for_status()
    except HTTPError as e:
        print e.response.status_code
        print e.response.content


if __name__ == '__main__':
    main()
Run Code Online (Sandbox Code Playgroud)

$ python test.py

418

-=[ teapot ]=-

   _...._
 .'  _ _ `.
| ."` ^ `". _,
\_;`"---"`|//
  |       ;/
  \_     _/
    `"""`
Run Code Online (Sandbox Code Playgroud)