381

I'm gathering statistics on a list of websites and I'm using requests for it for simplicity. Here is my code:

data=[] websites=['http://google.com', 'http://bbc.co.uk'] for w in websites: r= requests.get(w, verify=False) data.append( (r.url, len(r.content), r.elapsed.total_seconds(), str([(l.status_code, l.url) for l in r.history]), str(r.headers.items()), str(r.cookies.items())) ) 

Now, I want requests.get to timeout after 10 seconds so the loop doesn't get stuck.

This question has been of interest before too but none of the answers are clean.

I hear that maybe not using requests is a good idea but then how should I get the nice things requests offer (the ones in the tuple).

2

23 Answers 23

635

Note: The timeout param does NOT prevent the request from loading forever, it only stops if the remote server fails to send response data within the timeout value. It could still load indefinitely.

Set the timeout parameter:

try: r = requests.get("example.com", timeout=10) # 10 seconds except requests.exceptions.Timeout: print("Timed out") 

The code above will cause the call to requests.get() to timeout if the connection or delays between reads takes more than ten seconds.

The timeout parameter accepts the number of seconds to wait as a float, as well as a (connect timeout, read timeout) tuple.

See requests.request documentation as well as the timeout section of the "Advanced Usage" section of the documentation.

Sign up to request clarification or add additional context in comments.

9 Comments

Yes it is, in some circumstances. One of those circumstances happens to be yours. =) I invite you to look at the code if you're not convinced.
I just checked this and it never stopped: r = requests.get('ipv4.download.thinkbroadband.com/1GB.zip', timeout = 20)
Ah, sorry, I misunderstood what you meant when you said 'the entire response'. Yes, you're right: it's not an upper limit on the total amount of time to wait.
@GlenThomas a requests.exceptions.Timeout is raised. See DaWe's answer
|
174
+50

What about using eventlet? If you want to timeout the request after 10 seconds, even if data is being received, this snippet will work for you:

import requests import eventlet eventlet.monkey_patch() with eventlet.Timeout(10): requests.get("http://ipv4.download.thinkbroadband.com/1GB.zip", verify=False) 

7 Comments

Surely this is unnecessarily complicated.
Is eventlet.monkey_patch() required?
Yes, the socket module needs to be monkey patched, so at least you'll need a eventlet.monkey_patch(socket=True)
This comment from a requests developer has a good explanation of why requests does not have a total-response-time timeout, and what they suggest instead.
The combination of Python 3.7 + requests + eventlet.Timeout seems not to work anymore (either RecursionError or TypeError: wrap_socket() got an unexpected keyword argument '_context' depending on whether I use socket=True or socket=False for eventlet monkey patch). It was fine with earlier versions of Python... Good news however, I was successful in implementing the signal based solution from user totokaka below (stackoverflow.com/a/22156618/8046487)
|
157

UPDATE: https://requests.readthedocs.io/en/master/user/advanced/#timeouts

In new version of requests:

If you specify a single value for the timeout, like this:

r = requests.get('https://github.com', timeout=5) 

The timeout value will be applied to both the connect and the read timeouts. Specify a tuple if you would like to set the values separately:

r = requests.get('https://github.com', timeout=(3.05, 27)) 

If the remote server is very slow, you can tell Requests to wait forever for a response, by passing None as a timeout value and then retrieving a cup of coffee.

r = requests.get('https://github.com', timeout=None) 

My old (probably outdated) answer (which was posted long time ago):

There are other ways to overcome this problem:

1. Use the TimeoutSauce internal class

From: https://github.com/psf/requests/issues/1928#issuecomment-35811896

import requests from requests.adapters import TimeoutSauce class MyTimeout(TimeoutSauce): def __init__(self, *args, **kwargs): connect = kwargs.get('connect', 5) read = kwargs.get('read', connect) super(MyTimeout, self).__init__(connect=connect, read=read) requests.adapters.TimeoutSauce = MyTimeout 

This code should cause us to set the read timeout as equal to the connect timeout, which is the timeout value you pass on your Session.get() call. (Note that I haven't actually tested this code, so it may need some quick debugging, I just wrote it straight into the GitHub window.)

2. Use a fork of requests from kevinburke: https://github.com/kevinburke/requests/tree/connect-timeout

From its documentation: https://github.com/kevinburke/requests/blob/connect-timeout/docs/user/advanced.rst

If you specify a single value for the timeout, like this:

r = requests.get('https://github.com', timeout=5) 

The timeout value will be applied to both the connect and the read timeouts. Specify a tuple if you would like to set the values separately:

r = requests.get('https://github.com', timeout=(3.05, 27)) 

kevinburke has requested it to be merged into the main requests project, but it hasn't been accepted yet.

8 Comments

option 1 doesn't work. if you continue reading that thread, other people have said "this won't work for your use-case, I'm afraid. The read timeout function is at the scope of an individual socket recv() call, so that if the server stops sending data for more than the read timeout we'll abort."
There is another nice solution in that thread using Signal, which wouldn't work for me either, because I use Windows and signal.alarm is linux only.
@Kiarash I haven't tested it yet. However, as I understand when Lukasa said this won't work for you use-case. He meant it doesn't work with mp3 stream which is wanted by the other guy.
@Hieu - this was merged in another pull request - github.com/kennethreitz/requests/pull/…
timeout=None is not blocking the call.
|
80

Since requests >= 2.4.0, you can use the timeout argument, i.e:

requests.get('https://duckduckgo.com/', timeout=10)

You can also provide a tuple to specify connect and the read timeouts separately:

requests.get('https://duckduckgo.com/', timeout=(5, 8.5))

a None timeout will wait forever (not recommended)


Note:

timeout is not a time limit on the entire response download; rather, an exception is raised if the server has not issued a response for timeout seconds ( more precisely, if no bytes have been received on the underlying socket for timeout seconds). If no timeout is specified explicitly, requests do not time out.

2 Comments

What version of requests has the new timeout parameter?
Seems to be since version 2.4.0 : Support for connect timeouts! Timeout now accepts a tuple (connect, read) which is used to set individual connect and read timeouts. pypi.org/project/requests/2.4.0
50

In 2023, most other answers are incorrect. You will not achieve what you want.

TL;DR - the proper solution, condensed

import requests, sys, time TOTAL_TIMEOUT = 10 def trace_function(frame, event, arg): if time.time() - start > TOTAL_TIMEOUT: raise Exception('Timed out!') return trace_function start = time.time() sys.settrace(trace_function) try: res = requests.get('http://localhost:8080', timeout=(3, 6)) except: raise finally: sys.settrace(None) 

Read the explanation to understand why!

Despite all the answers, I believe that this thread still lacks a proper solution and no existing answer presents a reasonable way to do something which should be simple and obvious.

Let's start by saying that as of 2023, there is still absolutely no way to do it properly with requests alone. It is a concious design decision by the library's developers.

Solutions utilizing the timeout parameter simply do not accomplish what they intend to do. The fact that it "seems" to work at the first glance is purely incidental:

The timeout parameter has absolutely nothing to do with the total execution time of the request. It merely controls the maximum amount of time that can pass before underlying socket receives any data. With an example timeout of 5 seconds, server can just as well send 1 byte of data every 4 seconds and it will be perfectly okay, but won't help you very much.

Answers with stream and iter_content are somewhat better, but they still do not cover everything in a request. You do not actually receive anything from iter_content until after response headers are sent, which falls under the same issue - even if you use 1 byte as a chunk size for iter_content, reading full response headers could take a totally arbitrary amount of time and you can never actually get to the point in which you read any response body from iter_content.

Here are some examples that completely break both timeout and stream-based approach. Try them all. They all hang indefinitely, no matter which method you use.

server.py

import socket import time server = socket.socket() server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True) server.bind(('127.0.0.1', 8080)) server.listen() while True: try: sock, addr = server.accept() print('Connection from', addr) sock.send(b'HTTP/1.1 200 OK\r\n') # Send some garbage headers very slowly but steadily. # Never actually complete the response. while True: sock.send(b'a') time.sleep(1) except: pass 

demo1.py

import requests requests.get('http://localhost:8080') 

demo2.py

import requests requests.get('http://localhost:8080', timeout=5) 

demo3.py

import requests requests.get('http://localhost:8080', timeout=(5, 5)) 

demo4.py

import requests with requests.get('http://localhost:8080', timeout=(5, 5), stream=True) as res: for chunk in res.iter_content(1): break 

The proper solution

My approach utilizes Python's sys.settrace function. It is dead simple. You do not need to use any external libraries or turn your code upside down. Unlike most other answers, this actually guarantees that the code executes in specified time. Be aware that you still need to specify the timeout parameter, as settrace only concerns Python code. Actual socket reads are external syscalls which are not covered by settrace, but are covered by the timeout parameter. Due to this fact, the exact time limit is not TOTAL_TIMEOUT, but a value which is explained in comments below.

import requests import sys import time # This function serves as a "hook" that executes for each Python statement # down the road. There may be some performance penalty, but as downloading # a webpage is mostly I/O bound, it's not going to be significant. def trace_function(frame, event, arg): if time.time() - start > TOTAL_TIMEOUT: raise Exception('Timed out!') # Use whatever exception you consider appropriate. return trace_function # The following code will terminate at most after TOTAL_TIMEOUT + the highest # value specified in `timeout` parameter of `requests.get`. # In this case 10 + 6 = 16 seconds. # For most cases though, it's gonna terminate no later than TOTAL_TIMEOUT. TOTAL_TIMEOUT = 10 start = time.time() sys.settrace(trace_function) try: res = requests.get('http://localhost:8080', timeout=(3, 6)) # Use whatever timeout values you consider appropriate. except: raise finally: sys.settrace(None) # Remove the time constraint and continue normally. # Do something with the response 

That's it!

1 Comment

Be careful, start is not a function-local variable.
28

To create a timeout you can use signals.

The best way to solve this case is probably to

  1. Set an exception as the handler for the alarm signal
  2. Call the alarm signal with a ten second delay
  3. Call the function inside a try-except-finally block.
  4. The except block is reached if the function timed out.
  5. In the finally block you abort the alarm, so it's not singnaled later.

Here is some example code:

import signal from time import sleep class TimeoutException(Exception): """ Simple Exception to be called on timeouts. """ pass def _timeout(signum, frame): """ Raise an TimeoutException. This is intended for use as a signal handler. The signum and frame arguments passed to this are ignored. """ # Raise TimeoutException with system default timeout message raise TimeoutException() # Set the handler for the SIGALRM signal: signal.signal(signal.SIGALRM, _timeout) # Send the SIGALRM signal in 10 seconds: signal.alarm(10) try: # Do our code: print('This will take 11 seconds...') sleep(11) print('done!') except TimeoutException: print('It timed out!') finally: # Abort the sending of the SIGALRM signal: signal.alarm(0) 

There are some caveats to this:

  1. It is not threadsafe, signals are always delivered to the main thread, so you can't put this in any other thread.
  2. There is a slight delay after the scheduling of the signal and the execution of the actual code. This means that the example would time out even if it only slept for ten seconds.

But, it's all in the standard python library! Except for the sleep function import it's only one import. If you are going to use timeouts many places You can easily put the TimeoutException, _timeout and the singaling in a function and just call that. Or you can make a decorator and put it on functions, see the answer linked below.

You can also set this up as a "context manager" so you can use it with the with statement:

import signal class Timeout(): """ Timeout for use with the `with` statement. """ class TimeoutException(Exception): """ Simple Exception to be called on timeouts. """ pass def _timeout(signum, frame): """ Raise an TimeoutException. This is intended for use as a signal handler. The signum and frame arguments passed to this are ignored. """ raise Timeout.TimeoutException() def __init__(self, timeout=10): self.timeout = timeout signal.signal(signal.SIGALRM, Timeout._timeout) def __enter__(self): signal.alarm(self.timeout) def __exit__(self, exc_type, exc_value, traceback): signal.alarm(0) return exc_type is Timeout.TimeoutException # Demonstration: from time import sleep print('This is going to take maximum 10 seconds...') with Timeout(10): sleep(15) print('No timeout?') print('Done') 

One possible down side with this context manager approach is that you can't know if the code actually timed out or not.

Sources and recommended reading:

2 Comments

Signals are only delivered in the main thread, thus it defnitely won't work in other threads, not probably.
The timeout-decorator package provides a timeout decorator that uses signals (or optionally multiprocessing).
24

Try this request with timeout & error handling:

import requests try: url = "http://google.com" r = requests.get(url, timeout=10) except requests.exceptions.Timeout as e: print e 

1 Comment

If the site is unreachable, it throws requests.exceptions.ConnectionError instead of Timeout, so you might want to catch a more generic RequestException instead.
15

The connect timeout is the number of seconds Requests will wait for your client to establish a connection to a remote machine (corresponding to the connect()) call on the socket. It’s a good practice to set connect timeouts to slightly larger than a multiple of 3, which is the default TCP packet retransmission window.

Once your client has connected to the server and sent the HTTP request, the read timeout started. It is the number of seconds the client will wait for the server to send a response. (Specifically, it’s the number of seconds that the client will wait between bytes sent from the server. In 99.9% of cases, this is the time before the server sends the first byte).

If you specify a single value for the timeout, The timeout value will be applied to both the connect and the read timeouts. like below:

r = requests.get('https://github.com', timeout=5) 

Specify a tuple if you would like to set the values separately for connect and read:

r = requests.get('https://github.com', timeout=(3.05, 27)) 

If the remote server is very slow, you can tell Requests to wait forever for a response, by passing None as a timeout value and then retrieving a cup of coffee.

r = requests.get('https://github.com', timeout=None) 

https://docs.python-requests.org/en/latest/user/advanced/#timeouts

Comments

6

Set stream=True and use r.iter_content(1024). Yes, eventlet.Timeout just somehow doesn't work for me.

try: start = time() timeout = 5 with get(config['source']['online'], stream=True, timeout=timeout) as r: r.raise_for_status() content = bytes() content_gen = r.iter_content(1024) while True: if time()-start > timeout: raise TimeoutError('Time out! ({} seconds)'.format(timeout)) try: content += next(content_gen) except StopIteration: break data = content.decode().split('\n') if len(data) in [0, 1]: raise ValueError('Bad requests data') except (exceptions.RequestException, ValueError, IndexError, KeyboardInterrupt, TimeoutError) as e: print(e) with open(config['source']['local']) as f: data = [line.strip() for line in f.readlines()] 

The discussion is here https://redd.it/80kp1h

1 Comment

it's a shame request doesn't support maxtime params, this solution is the only one worked with asyncio
5

This may be overkill, but the Celery distributed task queue has good support for timeouts.

In particular, you can define a soft time limit that just raises an exception in your process (so you can clean up) and/or a hard time limit that terminates the task when the time limit has been exceeded.

Under the covers, this uses the same signals approach as referenced in your "before" post, but in a more usable and manageable way. And if the list of web sites you are monitoring is long, you might benefit from its primary feature -- all kinds of ways to manage the execution of a large number of tasks.

2 Comments

This could be a good solution. The problem of total timeout is not related directly to python-requests but to httplib (used by requests for Python 2.7). The package passes everything related to timeout directly to httplib. I think than nothing can be fixed in request because the process can stay for long time in httplib.
@hynekcer, I think you are right. This is why detecting timeouts out-of-process and enforcing by cleanly killing processes, as Celery does, can be a good approach.
5

I believe you can use multiprocessing and not depend on a 3rd party package:

import multiprocessing import requests def call_with_timeout(func, args, kwargs, timeout): manager = multiprocessing.Manager() return_dict = manager.dict() # define a wrapper of `return_dict` to store the result. def function(return_dict): return_dict['value'] = func(*args, **kwargs) p = multiprocessing.Process(target=function, args=(return_dict,)) p.start() # Force a max. `timeout` or wait for the process to finish p.join(timeout) # If thread is still active, it didn't finish: raise TimeoutError if p.is_alive(): p.terminate() p.join() raise TimeoutError else: return return_dict['value'] call_with_timeout(requests.get, args=(url,), kwargs={'timeout': 10}, timeout=60) 

The timeout passed to kwargs is the timeout to get any response from the server, the argument timeout is the timeout to get the complete response.

2 Comments

This can be improved with a generic try/except in the private function that catches all errors and puts them in return_dict['error']. Then at the end, before returning, check if 'error' in return_dict and then raise it. It makes it much easier to test as well.
What about starting a thread (not a heavy Process) instead?
2

Despite the question being about requests, I find this very easy to do with pycurl CURLOPT_TIMEOUT or CURLOPT_TIMEOUT_MS.

No threading or signaling required:

import pycurl import StringIO url = 'http://www.example.com/example.zip' timeout_ms = 1000 raw = StringIO.StringIO() c = pycurl.Curl() c.setopt(pycurl.TIMEOUT_MS, timeout_ms) # total timeout in milliseconds c.setopt(pycurl.WRITEFUNCTION, raw.write) c.setopt(pycurl.NOSIGNAL, 1) c.setopt(pycurl.URL, url) c.setopt(pycurl.HTTPGET, 1) try: c.perform() except pycurl.error: traceback.print_exc() # error generated on timeout pass # or just pass if you don't want to print the error 

Comments

2

Just another one solution (got it from http://docs.python-requests.org/en/master/user/advanced/#streaming-uploads)

Before upload you can find out the content size:

TOO_LONG = 10*1024*1024 # 10 Mb big_url = "http://ipv4.download.thinkbroadband.com/1GB.zip" r = requests.get(big_url, stream=True) print (r.headers['content-length']) # 1073741824 if int(r.headers['content-length']) < TOO_LONG: # upload content: content = r.content 

But be careful, a sender can set up incorrect value in the 'content-length' response field.

Comments

2

timeout = (connection timeout, data read timeout) or give a single argument(timeout=1)

import requests try: req = requests.request('GET', 'https://www.google.com',timeout=(1,1)) print(req) except requests.ReadTimeout: print("READ TIME OUT") 

Comments

1

this code working for socketError 11004 and 10060......

# -*- encoding:UTF-8 -*- __author__ = 'ACE' import requests from PyQt4.QtCore import * from PyQt4.QtGui import * class TimeOutModel(QThread): Existed = pyqtSignal(bool) TimeOut = pyqtSignal() def __init__(self, fun, timeout=500, parent=None): """ @param fun: function or lambda @param timeout: ms """ super(TimeOutModel, self).__init__(parent) self.fun = fun self.timeer = QTimer(self) self.timeer.setInterval(timeout) self.timeer.timeout.connect(self.time_timeout) self.Existed.connect(self.timeer.stop) self.timeer.start() self.setTerminationEnabled(True) def time_timeout(self): self.timeer.stop() self.TimeOut.emit() self.quit() self.terminate() def run(self): self.fun() bb = lambda: requests.get("http://ipv4.download.thinkbroadband.com/1GB.zip") a = QApplication([]) z = TimeOutModel(bb, 500) print 'timeout' a.exec_() 

1 Comment

Upvoting for creativity
1

Well, I tried many solutions on this page and still faced instabilities, random hangs, poor connections performance.

I'm now using Curl and i'm really happy about it's "max time" functionnality and about the global performances, even with such a poor implementation :

content=commands.getoutput('curl -m6 -Ss "http://mywebsite.xyz"') 

Here, I defined a 6 seconds max time parameter, englobing both connection and transfer time.

I'm sure Curl has a nice python binding, if you prefer to stick to the pythonic syntax :)

Comments

1

In case you're using the option stream=True you can do this:

r = requests.get( 'http://url_to_large_file', timeout=1, # relevant only for underlying socket stream=True) with open('/tmp/out_file.txt'), 'wb') as f: start_time = time.time() for chunk in r.iter_content(chunk_size=1024): if chunk: # filter out keep-alive new chunks f.write(chunk) if time.time() - start_time > 8: raise Exception('Request took longer than 8s') 

The solution does not need signals or multiprocessing.

1 Comment

this wont work if the target server stops streaming data. you will be locked forever at the iter line. such situations happen when your auth session expires for example.
1

There is a package called timeout-decorator that you can use to time out any python function.

@timeout_decorator.timeout(5) def mytest(): print("Start") for i in range(1,10): time.sleep(1) print("{} seconds have passed".format(i)) 

It uses the signals approach that some answers here suggest. Alternatively, you can tell it to use multiprocessing instead of signals (e.g. if you are in a multi-thread environment).

1 Comment

Note that this approach doesn't work on Windows.
1

The biggest problem is that if the connection can't be established, the requests package waits too long and blocks the rest of the program.

There are several ways how to tackle the problem but when I looked for a oneliner similar to requests, I couldn't find anything. That's why I built a wrapper around requests called reqto ("requests timeout"), which supports proper timeout for all standard methods from requests.

pip install reqto 

The syntax is identical to requests

import reqto response = reqto.get(f'https://pypi.org/pypi/reqto/json',timeout=1) # Will raise an exception on Timeout print(response) 

Moreover, you can set up a custom timeout function

def custom_function(parameter): print(parameter) response = reqto.get(f'https://pypi.org/pypi/reqto/json',timeout=5,timeout_function=custom_function,timeout_args="Timeout custom function called") #Will call timeout_function instead of raising an exception on Timeout print(response) 

Important note is that the import line

import reqto 

needs to be earlier import than all other imports working with requests, threading, etc. due to monkey_patch which runs in the background.

Comments

0

If it comes to that, create a watchdog thread that messes up requests' internal state after 10 seconds, e.g.:

  • closes the underlying socket, and ideally
  • triggers an exception if requests retries the operation

Note that depending on the system libraries you may be unable to set deadline on DNS resolution.

Comments

0

I'm using requests 2.2.1 and eventlet didn't work for me. Instead I was able use gevent timeout instead since gevent is used in my service for gunicorn.

import gevent import gevent.monkey gevent.monkey.patch_all(subprocess=True) try: with gevent.Timeout(5): ret = requests.get(url) print ret.status_code, ret.content except gevent.timeout.Timeout as e: print "timeout: {}".format(e.message) 

Please note that gevent.timeout.Timeout is not caught by general Exception handling. So either explicitly catch gevent.timeout.Timeout or pass in a different exception to be used like so: with gevent.Timeout(5, requests.exceptions.Timeout): although no message is passed when this exception is raised.

Comments

0

I chose Python3 multiprocessing with a process to get reliable timeout behavior, and a shared queue to fetch the result back. I am pretty confident this is safe in multiprocessing, for example if you have a worker thread. I also believe this runs on Windows.

from concurrent.futures import Future, ThreadPoolExecutor from multiprocessing import Process, Queue from requests import Response, post def post_request(url: str, payload: dict, queue: Queue = None) -> str: """ POST a request to the given URL and the given payload. The `timeout` feature in requests.post() is not reliable. :param url: URL to POST to :param payload: payload of the POST request :param queue: Queue to receive the response; may be None :return: string returned by the remote server. """ post_timeout = 2 print(f'POST to URL {url} with timeout {post_timeout}') resp: Response = post( url=url, timeout=float(post_timeout), json=payload) print(f'Response {resp.text}') if queue: # running in a process, enqueue the response queue.put(resp.text) # response is ignored if running in a process return resp.text def post_in_thread(url: str, payload: dict) -> str: """ Send a payload to a client system within a thread. This detects timeout but does not end the hung thread. :param url: URL to POST to :param payload: dict to serialize as JSON :return: result :raises TimeoutError: if the request fails to complete """ thread_timeout = 5 print(f'use thread timeout {thread_timeout} sec') executor = ThreadPoolExecutor( max_workers=1, thread_name_prefix='client_request') # submit returns a Future object future: Future = executor.submit(post_request, url, payload) # wait for completion and raise any exception that happened # in the called function; raise TimeoutError on timeout. result = future.result(timeout=thread_timeout) # this line is not reached if timeout happens print(f'return {result}') return result def post_in_process(url: str, payload: dict) -> str: """ Send a payload to a client system within a process for reliable timeout, and read response from a shared queue. :param url: URL to POST to :param payload: dict to serialize as JSON :return: result on success; None on time out """ process_timeout = 5 print(f'use process timeout {process_timeout} sec') q = Queue() p = Process(target=post_request, args=[url, payload, q]) p.start() p.join(process_timeout) if p.is_alive(): print('Timeout, terminate process') p.terminate() return None else: return q.get() if __name__ == '__main__': url = 'http://localhost:8080' payload = {'foo': 'bar'} try: # post_in_thread(url, payload) r = post_in_process(url, payload) print(r) except TimeoutError as e: print(repr(e)) print('main ends') # Python interpreter waits for all threads to exit 

Run the server.py code posted above by @tim-colorado to test this. I left the post_in_thread function so you can see that the Python interpreter waits for that thread to finish before exiting. As far as I can tell, there is no way to terminate that thread. So a long-running process that suffers many time-outs might gather quite a few hung threads :(

Comments

-1

I came up with a more direct solution that is admittedly ugly but fixes the real problem. It goes a bit like this:

resp = requests.get(some_url, stream=True) resp.raw._fp.fp._sock.settimeout(read_timeout) # This will load the entire response even though stream is set content = resp.content 

You can read the full explanation here

1 Comment

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.