引发异常时如何从请求GET调用获取响应对象

时间:2019-04-30 22:53:18

标签: python python-requests

当请求抛出异常时,如何从请求中获取响应对象?

本质上,我正在尝试通过代理发出请求,并且代理正在返回302代码(这是我想要的)。但是,在进行一些调试之后,我发现在requests库中,它期望来自代理的200条代码,否则将引发异常。

这是我正在执行的命令:

session.get(url=url, headers=req_headers, verify=False, allow_redirects=True, timeout=30)

这给了我(Caused by ProxyError('Cannot connect to proxy.', OSError('Tunnel connection failed: 302 Object Moved'))。这是我期望从代理获得的正确行为,但是我需要响应对象,因为响应对象具有逻辑中需要的有用信息,现在我只能得到错误消息。有没有办法我仍然可以获取响应对象而不必修改requests库?

感谢您的帮助!

编辑:

def _tunnel(self):
    connect_str = "CONNECT %s:%d HTTP/1.0\r\n" % (self._tunnel_host,
        self._tunnel_port)
    connect_bytes = connect_str.encode("ascii")
    self.send(connect_bytes)
    for header, value in self._tunnel_headers.items():
        header_str = "%s: %s\r\n" % (header, value)
        header_bytes = header_str.encode("latin-1")
        self.send(header_bytes)
    self.send(b'\r\n')

    response = self.response_class(self.sock, method=self._method)
    (version, code, message) = response._read_status()

    if code != http.HTTPStatus.OK:
        self.close()
        raise OSError("Tunnel connection failed: %d %s" % (code,
                                                           message.strip()))

我已对其进行调试,以使我知道代码正在引发OSError,并且仅提供状态代码和消息。我想做的就是也将response传递给该异常,但是同时我不想更改该库,因为我希望有一种方法可以在不更改lib的情况下

2 个答案:

答案 0 :(得分:1)

从源代码看,Requests中的ProxyError异常对象看起来像该对象中应该包含请求。我知道您说过您认为不行,但这表明它至少要在其中放置一个response字段,即使该字段最终以null结尾。

我可能会将其放在注释中,但是您无法在此处格式化代码。这种确定似乎可以给您想要的东西,

class RequestException(IOError):
    """There was an ambiguous exception that occurred while handling your
    request.
    """

    def __init__(self, *args, **kwargs):
        """Initialize RequestException with `request` and `response` objects."""
        response = kwargs.pop('response', None)
        self.response = response
        self.request = kwargs.pop('request', None)
        if (response is not None and not self.request and
                hasattr(response, 'request')):
            self.request = self.response.request
        super(RequestException, self).__init__(*args, **kwargs)

class ConnectionError(RequestException):
    """A Connection error occurred."""

class ProxyError(ConnectionError):
    """A proxy error occurred."""

因此,看到此代码,似乎可以进行以下操作:

try:
    ...
    session.get(url=url, headers=req_headers, verify=False, allow_redirects=True, timeout=30)
    ...
except ProxyError as ex:
    the_response = ex.response
    .. do something with the response ..

答案 1 :(得分:0)

我认为您也许可以使用Request的history功能访问该对象,然后使用Request的标准API:

https://2.python-requests.org//en/latest/user/quickstart/#redirection-and-history

  

默认情况下,请求将对所有动词执行位置重定向   除了HEAD。

     

我们可以使用Response对象的history属性来跟踪   重定向。

     

Response.history列表包含以下响应对象:   创建以完成请求。该列表从   从最早到最新的响应。

r = requests.get('http://github.com/')

r.url 'https://github.com/'

r.status_code 200

r.history [<Response [301]>]

headers会不给您您所需要的吗?

https://2.python-requests.org//en/latest/user/advanced/#advanced

>>> r.headers
{'content-length': '56170', 'x-content-type-options': 'nosniff', 'x-cache':
'HIT from cp1006.eqiad.wmnet, MISS from cp1010.eqiad.wmnet', 'content-encoding':
'gzip', 'age': '3080', 'content-language': 'en', 'vary': 'Accept-Encoding,Cookie',
'server': 'Apache', 'last-modified': 'Wed, 13 Jun 2012 01:33:50 GMT',
'connection': 'close', 'cache-control': 'private, s-maxage=0, max-age=0,
must-revalidate', 'date': 'Thu, 14 Jun 2012 12:59:39 GMT', 'content-type':
'text/html; charset=UTF-8', 'x-cache-lookup': 'HIT from cp1006.eqiad.wmnet:3128,
MISS from cp1010.eqiad.wmnet:80'}