If the requests library (as used by grequests) returns None
as the response (for whatever reason), grequests lets you handle that however you'd like, by calling an exception handler callback function that you create and then pass to map
.
From grequests.py
(in the map
method):
for request in requests:
if request.response is not None:
ret.append(request.response)
elif exception_handler and hasattr(request, 'exception'):
ret.append(exception_handler(request, request.exception))
elif exception_handler and not hasattr(request, 'exception'):
ret.append(exception_handler(request, None))
else:
ret.append(None)
What is happening here? Before this block executes, grequests will have raised all of the requests, and now we're looping through the results. For each request:
- If you get a
response
, return that.
- If an exception handler is registered and the
request
has an exception
defined, call the handler and pass it the request
and exception
.
- If an exception handler is registered and the
request
does not have an exception
defined, call the handler and pass it the request
.
- If the
response
was None
, but no handler is registered, return None
The last case results in data loss, but it's preventable by using a callback that properly handles the exception. What exactly exception_handler
does is something you need to define, then include like this:
response = grequests.map(request_getters, exception_handler=my_handler)
what the handler does is up to you, but maybe this would be helpful:
MAX_PARALLEL_REQUESTS = 2
links = [
'https://api.github.com/users?since=135',
'http://www.google.com',
'https://api.github.com/users?since=135',
'http://www.google.com'
]
def my_handler(request, exception):
links.append(request.url)
print(f"exception thrown by grequests: \n{exception}")
return request
while links:
a = (grequests.get(links.pop(0)) for _ in range(MAX_PARALLEL_REQUESTS))
p = grequests.map(a, exception_handler=my_handler)
print(p)
This is pop a fixed number of URL's off the links
list each iteration of the while
loop. If any of those requests should fail, my_handler
is called, which adds the failed URL back to the links
list for reprocessing.