Python请求:如何确定MaxRetries异常的响应代码

时间:2019-01-24 23:14:02

标签: python python-requests

当get或post出现错误响应直到超过最大重试次数时,我想知道问题的原因。

我在下面有一个示例测试。如预期的那样,这将引发MaxRetriesError。但是,原始的HTTPError似乎丢失了。

from requests import Session, exceptions
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry
from unittest import TestCase
import logging


class TestRequests(TestCase):

    def test_retries(self):
        session = Session()
        retries = Retry(total=5,
                        backoff_factor=0.1,
                        status_forcelist=[500, 502, 503, 504],
                        method_whitelist=frozenset(['GET', 'POST']))

        session.mount('https://', HTTPAdapter(max_retries=retries))
        session.mount('http://', HTTPAdapter(max_retries=retries))

        try:
            result = session.get('https://httpbin.org/status/500',
                                 stream=True,
                                 timeout=2)
            print(result)
        except exceptions.HTTPError as e:
            logging.error('http', exc_info=e)
        except exceptions.RetryError as e:
            logging.error('retry', exc_info=e)

Traceback显示以下信息,它仅返回到最后一个RetryError,而不返回到HTTPError。异常的字符串确实提到了响应代码,但是解析错误消息字符串并不是一种可靠的方法。

ERROR:root:retry
Traceback (most recent call last):
  File "/home/giles/venv/gphotos-sync3/lib/python3.6/site-packages/requests/adapters.py", line 449, in send
    timeout=timeout
  File "/home/giles/venv/gphotos-sync3/lib/python3.6/site-packages/urllib3/connectionpool.py", line 731, in urlopen
    body_pos=body_pos, **response_kw)
  File "/home/giles/venv/gphotos-sync3/lib/python3.6/site-packages/urllib3/connectionpool.py", line 731, in urlopen
    body_pos=body_pos, **response_kw)
  File "/home/giles/venv/gphotos-sync3/lib/python3.6/site-packages/urllib3/connectionpool.py", line 731, in urlopen
    body_pos=body_pos, **response_kw)
  [Previous line repeated 2 more times]
  File "/home/giles/venv/gphotos-sync3/lib/python3.6/site-packages/urllib3/connectionpool.py", line 711, in urlopen
    retries = retries.increment(method, url, response=response, _pool=self)
  File "/home/giles/venv/gphotos-sync3/lib/python3.6/site-packages/urllib3/util/retry.py", line 398, in increment
    raise MaxRetryError(_pool, url, error or ResponseError(cause))
urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='httpbin.org', port=443): Max retries exceeded with url: /status/500 (Caused by ResponseError('too many 500 error responses',))

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/giles/github/gphotos-sync/test/test_requests.py", line 36, in test_retries
    timeout=2)
  File "/home/giles/venv/gphotos-sync3/lib/python3.6/site-packages/requests/sessions.py", line 546, in get
    return self.request('GET', url, **kwargs)
  File "/home/giles/venv/gphotos-sync3/lib/python3.6/site-packages/requests/sessions.py", line 533, in request
    resp = self.send(prep, **send_kwargs)
  File "/home/giles/venv/gphotos-sync3/lib/python3.6/site-packages/requests/sessions.py", line 646, in send
    r = adapter.send(request, **kwargs)
  File "/home/giles/venv/gphotos-sync3/lib/python3.6/site-packages/requests/adapters.py", line 507, in send
    raise RetryError(e, request=request)
requests.exceptions.RetryError: HTTPSConnectionPool(host='httpbin.org', port=443): Max retries exceeded with url: /status/500 (Caused by ResponseError('too many 500 error responses',))


Ran 1 test in 4.092s

OK

1 个答案:

答案 0 :(得分:0)

我发现,如果我告诉Retries不要提出自己的错误(raise_on_status = False),而是检查最后一个响应,则可以看到原始错误。请参阅下面的修改代码。

from requests import Session, exceptions
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry
from urllib3.exceptions import MaxRetryError
from unittest import TestCase
import logging


class TestRequests(TestCase):

    def test_retries(self):
        session = Session()
        retries = Retry(total=5,
                        backoff_factor=0.1,
                        status_forcelist=[500, 502, 503, 504],
                        method_whitelist=frozenset(['GET', 'POST']),
                        raise_on_status=False)

        session.mount('https://', HTTPAdapter(max_retries=retries))
        session.mount('http://', HTTPAdapter(max_retries=retries))

        try:
            result = session.get('https://httpbin.org/status/500',
                                 stream=True,
                                 timeout=2)
            print(result)
            result.raise_for_status()

        except exceptions.HTTPError as e:
            logging.error('http', exc_info=e)
        except MaxRetryError as e:
            logging.error('retry', exc_info=e)

结果是:

------------------------------------------------------------- Captured stdout call --------------------------------------------------------------
<Response [500]>
--------------------------------------------------------------- Captured log call ---------------------------------------------------------------
test-requests.py            30 ERROR    http
Traceback (most recent call last):
  File "/home/hgv27681/github/tests/test-requests.py", line 27, in test_retries
    result.raise_for_status()
  File "/home/hgv27681/github/venv3/lib/python3.6/site-packages/requests/models.py", line 940, in raise_for_status
    raise HTTPError(http_error_msg, response=self)
requests.exceptions.HTTPError: 500 Server Error: INTERNAL SERVER ERROR for url: https://httpbin.org/status/500