我宁愿创建自己的“响应流”以防万一,而不是使用任何类型的monkey patching。我已经检查了请求库的来源,我们很高兴去那里!我们可以使用requests Event Hooks system 实现所需的功能。
有一个工作示例,我们可以对响应做任何事情。唯一的变化是我们必须使用我们自己的Session 对象实例来使用该功能。但!如果我们不想覆盖任何源代码,我们可以做一个 linemonkey-patch,覆盖默认 api 调用的默认 Session 类,它可以像魅力一样在任何地方工作。
我的解决方案在这里
import requests
class ResponseVerbose(requests.Response):
extra_header_repr = 'X-Request-Guid'
def __repr__(self):
return '<Response [{}] {}: {}>'.format(
self.status_code,
self.extra_header_repr,
self.headers.get(self.extra_header_repr, 'None')
)
class Session(requests.Session):
def __init__(self):
super().__init__()
self.hooks['response'] = self.build_response
@staticmethod
def build_response(resp, *args, **kwargs):
"""
Let's rebuild the source response into required verbose response object using all fields from the original
FYI: requests.adapters.HTTPAdapter.build_response
"""
response = ResponseVerbose()
response.status_code = resp.status_code
response.headers = resp.headers
response.encoding = resp.encoding
response.raw = resp.raw
response.reason = response.raw.reason
response.url = resp.url
response.cookies = resp.cookies.copy()
response.request = resp.request
response.connection = resp.connection
return response
def main():
url = 'https://stackoverflow.com/'
sess = Session()
print('response using our own session object: {}'.format(sess.get(url)))
import requests.api
requests.api.sessions.Session = Session
print('response using monkey patched global Session class: {}'.format(requests.get(url)))
if __name__ == '__main__':
main()
输出
# python test123.py
response using our own session object: <Response [200] X-Request-Guid: 0c446bb5-7c96-495d-a831-061f5e3c2afe>
response using monkey patched global Session class: <Response [200] X-Request-Guid: 1db5aea7-8bc9-496a-addc-1231e8543a89>
一个使用Response.__getstate__()函数的更短示例
更多信息https://github.com/psf/requests/blob/master/requests/models.py#L654
正如我从源代码中看到的,您不应该对非常大的内容响应执行此操作,因为它会获取整个 resp.content 以便能够将响应状态转换为状态字典。因此,仅当您知道响应中没有千兆字节时才使用它:)
函数看起来更简单。
import requests
class ResponseVerbose(requests.Response):
extra_header_repr = 'X-Request-Guid'
def __repr__(self):
return '<Response [{}] {}: {}>'.format(
self.status_code,
self.extra_header_repr,
self.headers.get(self.extra_header_repr, 'None')
)
class Session(requests.Session):
def __init__(self):
super().__init__()
self.hooks['response'] = self.build_response
@staticmethod
def build_response(resp, *args, **kwargs):
"""
Let's rebuild the source response into required verbose response object using all fields from the original
FYI: requests.adapters.HTTPAdapter.build_response
"""
response = ResponseVerbose()
for k, v in resp.__getstate__().items():
setattr(response, k, v)
return response
def main():
url = 'https://stackoverflow.com/'
sess = Session()
print('response using our own session object: {}'.format(sess.get(url)))
import requests.api
requests.api.sessions.Session = Session
print('response using monkey patched global Session class: {}'.format(requests.get(url)))
if __name__ == '__main__':
main()
该解决方案仅打印 StackOverflow 的额外响应标头X-Request-Guid。这个额外的标题我很容易配置,只是为了展示如何以正确的方式完成。