如何在Python请求中将响应归类?

时间:2019-07-09 14:38:50

标签: python python-requests

在我的用例中,很好的子类化Python响应类以启用诸如此类的功能

session = requests.Session()
response = session.get('/resource/')
response.custom_methods_on_response_object()

我希望能够在响应类上添加自定义方法。像.json之类的东西很有用,但是如果我可以使用自定义方法将响应转换为更多可用的数据,它将更有用。

但是,如果不对会话对象进行过多的子类化,我将不清楚如何做到这一点。

3 个答案:

答案 0 :(得分:0)

虽然不对响应进行子类化,但是使用挂钩可以实现类似的效果。相对于其他答案,此方法的优势在于,猴子补丁的作用范围仅限于响应(而不是整个类)。

  

https://requests.kennethreitz.org/en/master/user/advanced/#event-hooks

def record_hook(r, *args, **kwargs):
    r.model = MyModel(**r.json())
    return r

答案 1 :(得分:0)

要在请求中执行响应类的真正子类,可以执行以下操作。

from requests.models import Response
from requests.adapters import HTTPAdapter
from requests import Session


class CustomResponse(Response)
   """
   Override response class with additional methods
   """
   # add additional attrs
   __attrs__ = Response.__attrs__ + ['method_name']


class CustomHttpAdapter(HTTPAdapter):
    def build_response(self, req, resp):
        response = CustomResponse()

        # Fallback to None if there's no status_code, for whatever reason.
        response.status_code = getattr(resp, 'status', None)

        # Make headers case-insensitive.
        response.headers = CaseInsensitiveDict(getattr(resp, 'headers', {}))

        # Set encoding.
        response.encoding = get_encoding_from_headers(response.headers)
        response.raw = resp
        response.reason = response.raw.reason

        if isinstance(req.url, bytes):
            response.url = req.url.decode('utf-8')
        else:
            response.url = req.url

        # Add new cookies from the server.
        extract_cookies_to_jar(response.cookies, req, resp)

        # Give the Response some context.
        response.request = req
        response.connection = self

        return response


session = Session()

session.mount(
    'https://', CustomHttpAdapter()
)

答案 2 :(得分:-1)

方法只是在对象上工作的函数(基本上是字典),因此,使用方法进行的任何操作都可以使用普通函数来完成。您唯一松动的是多态调度,但是您可能在这里不需要它。

例如,如果Response还没有json方法,则可以将其写为

def to_json(response):
    return json.loads(response.text)

然后写reponse.json()代替to_json(response)

现在,如果您真的想改用obj.method()语法,则可以随时对Response类进行修补:

import requests
from requests.models import Response


def revtext(response):
    return response.text[::-1]

Response.revtext = revtext


r = requests.get("https://stackoverflow.com")
print(r.revtext())

但这通常不是一个好主意。