How to override the .get() method in requests?
Question: I would like the `.get()` method in `requests` to do extra operations beside
the `GET` itself:

  * print out "hello world" (in reality this will be logging)
  * wait 5 seconds before issuing the actual `GET` (in reality this will be a more complex wait-and-retry operation)

Right now my simplistic solution is to use a function which actually calls
`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
    

but I have a strong feeling that it would be possible to override the actual
`.get()` method in requests.

I use object programming in a very basic way and that would be an opportunity
to actually learn the override part. There are
[various](http://blog.devzero.com/2013/01/28/how-to-override-a-class-method-
in-python/) [tutorials](http://lgiordani.com/blog/2014/05/19/method-
overriding-in-python/) on how to override and call the parent class methods
(which is exactly what I want to do: be able to finally use the original
`.get()` method)

I therefore tried a basic override:

    
    
    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')
    

This code fails with

    
    
    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'
    

To be honest, I am stuck here. The tutorials all start with a definition of
the parent class, while what I have is hidden (there is
[documentation](http://docs.python-requests.org/en/latest/api/))


Answer: [`requests.get` is just a
function](https://github.com/kennethreitz/requests/blob/master/requests/api.py#L57-L65),
you can override it. It is _not_ a method on the `requests.Requests` model:

    
    
    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
    

This then uses a _new session object_ to handle the request.

Instead of replacing `requests.get()`, I'd provide a subclass of the
`requests.Session()` object instead, overriding the [`Session.request()`
method](https://github.com/kennethreitz/requests/blob/master/requests/sessions.py#L382-L463),
then use an instance of that session object:

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

then use that like this:

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

The advantage here is that you then can also make use of the full feature set
that session objects offer, plus your additional code will also work for POST
and PUT and DELETE and HEAD, etc. requests.

