如何覆盖请求中的 .get() 方法?

How to override the .get() method in requests?

我希望 requests 中的 .get() 方法在 GET 本身之外做额外的操作:

现在我的简单解决方案是使用一个实际调用 requests.get():

的函数
def multiple_requests(self, url, retries=5, wait=5):
        """
        retries several times an URL
        :param
        url: the url to check
        retries: how meny times to retry
        wait: number of seconds to wait between retries
        :return: the requests response, or None if failed
        """
        for _ in range(retries):
            try:
                r = requests.get(url)
            except Exception as e:
                self.log.error("cannot connect to {url}: {e}, retrying in {wait} seconds".format(url=url, e=e, wait=wait))
            else:
                if r.ok:
                    return r
                else:
                    self.log.error(
                        "error connecting to {url}, code {e}, retrying in {wait} seconds".format(
                            url=url, e=r.status_code, wait=wait
                        )
                    )
            finally:
                time.sleep(wait)
        # give up after several tries
        self.log.error("cannot connect to {url} despite retries, giving up".format(url=url))
        return None

但我有一种强烈的感觉,即可以覆盖请求中实际的 .get() 方法。

我以非常基本的方式使用对象编程,这将是一个真正学习覆盖部分的机会。关于如何覆盖和调用父class方法有various tutorials(这正是我想做的:能够最终使用原始.get()方法)

因此我尝试了一个基本的覆盖:

import requests

class MyRequest(requests.Request):
    def get(self, url, **kwargs):
        print("hello world")
        # calling the parent .get() method to actually GET something
        super(MyRequest, self).get(url, **kwargs)

r = MyRequest.get('http://google.com')

此代码失败

Traceback (most recent call last):
  File "C:/Users/yop/dev/infoscreen/testingrequestsclass.py", line 8, in <module>
    r = MyRequest.get('http://google.com')
TypeError: get() missing 1 required positional argument: 'url'

老实说,我被困在这里了。教程都是从父class的定义开始的,而我有的是隐藏的(有documentation

requests.get is just a function,你可以覆盖它。 不是 requests.Requests 模型上的方法:

import requests.api

def my_get(url, **kwargs):
    print('Hello World!')
    kwargs.setdefault('allow_redirects', True)
    return requests.api.request('get', url, **kwargs)

requests.api.get = my_get

然后使用新会话对象来处理请求。

我不会替换 requests.get(),而是提供 requests.Session() 对象的子类,覆盖 Session.request() method,然后使用该会话对象的实例:

from requests import Session

class MySession(Session):
    def request(self, method, url, **kwargs):
        print('Hello World!')
        return super().request(method, url, **kwargs)

然后像这样使用它:

with MySession() as session:
    response = session.get(url)

这里的优点是您还可以利用会话对象提供的完整功能集,而且您的附加代码也适用于 POST 和 PUT、DELETE 和 HEAD 等请求。