如何在抛出异常时从请求中获取响应对象?
本质上,我正在尝试通过代理发出请求,代理正在返回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的情况下执行此操作
它在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 ..
我认为您可以使用Request的history
功能来访问该对象,并且可以使用Request的标准API:
https://2.python-requests.org//en/latest/user/quickstart/#redirection-and-history
默认情况下,Requests将为除HEAD之外的所有动词执行位置重定向。
我们可以使用Response对象的history属性来跟踪重定向。
Response.history列表包含为完成请求而创建的Response对象。该列表从最旧的响应到最新的响应排序。
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'}