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

时间:2015-03-12 10:20:22

标签: python override python-requests

我希望.get()中的requests方法在GET本身旁边执行额外的操作:

  • 打印出“hello world”(实际上这将是记录)
  • 在发出实际GET之前等待5秒(实际上这将是一个更复杂的等待和重试操作)

现在,我的简单解决方案是使用实际调用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()方法。

我以非常基本的方式使用对象编程,这将是实际学习覆盖部分的机会。关于如何覆盖和调用父类方法有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'

说实话,我被困在这里。教程都以父类的定义开始,而我隐藏的内容(有documentation

1 个答案:

答案 0 :(得分:4)

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等请求。