Search code examples
pythonpython-2.7python-requestsattributeerror

AttributeError using hooks in Requests Python package


I am sending requests and receiving their response objects into a hooked function. Sometimes, I'm sending a new request out of that same function, which in turns calls the function that sends requests (with a new thread for each request).

That creates the following exception in the Requests module itself:

Exception in thread Thread-103:
Traceback (most recent call last):
  File "/usr/lib/python2.7/threading.py", line 810, in __bootstrap_inner
    self.run()
  File "/usr/lib/python2.7/threading.py", line 763, in run
    self.__target(*self.__args, **self.__kwargs)
  File "/api.py", line 272, in thread_func
    r = self.session.post(url, data=params, headers=headers, timeout=60, hooks=dict(response=self.http_callback))
  File "/usr/lib/python2.7/dist-packages/requests/sessions.py", line 425, in post
    return self.request('POST', url, data=data, **kwargs)
  File "/usr/lib/python2.7/dist-packages/requests/sessions.py", line 383, in request
    resp = self.send(prep, **send_kwargs)
  File "/usr/lib/python2.7/dist-packages/requests/sessions.py", line 494, in send
    if r.history:
AttributeError: 'bool' object has no attribute 'history'

I find that very strange. Do you know what might be happening?

Note: I looked at this question but my problem is different: Problems with hooks using Requests Python package


Solution

  • The line before the exception point reads:

    r = dispatch_hook('response', hooks, r, **kwargs)
    

    Your hook returned a boolean, while it should return a response object. A boolean doesn't have a history attribute, while a response object would.

    Alternatively, return None if you did not mean to alter the response.

    From the event hooks documentation:

    If the callback function returns a value, it is assumed that it is to replace the data that was passed in. If the function doesn’t return anything, nothing else is effected.

    The value passed in for the response hook is the response object; the replacement value should be a response object too.

    Fix your hook. From your traceback we can see that you passed in self.http_callback as the hook, if you were wondering where to look.