I have a very sensitive production script that I’ve been running consistently for the past 4 years. This specific function (runAPI) is called about 100 times every day and has never caused any issues — until today.
I just want the function to exit, if request fails WITHOUT CRASHING/STOPPING THE WHOLE PROGRAM
Today, my code froze while executing the runAPI() function. It did not proceed to any lines of code after the function call, and I was unable to exit from it. This is surprising because I've set a timeout=2 in the requests call, and I expected it to fail gracefully in at most 2 seconds if there was an issue.
Here are the two possible changes that might have triggered this:
I recently switched my GCP virtual machine. However, I reinstalled all libraries and dependencies in the new server.
The target API server might be experiencing issues (I'm currently unable to reach their support).
Both of these possibilities seem unlikely to cause such a complete freeze, so I'm unsure what's going wrong.
Here’s the relevant code snippet:
import requests
import json
def runAPI():
orderParams = {
"someparameterhere": "example",
"moreparameterhere": "example"
}
headerData = {
'Content-type': 'application/json',
'X-ClientLocalIP': '11.161.0.23',
'X-ClientPublicIP': '11.22.55.66',
'X-MACAddress': '32:01:0a:a0:00:16',
'Accept': 'application/json',
'X-PrivateKey': 'privatekeyhere',
'X-UserType': 'USER',
'X-SourceID': 'WEB',
'Authorization': 'Bearer somelongstringhere.'
}
for j in range(1):
try:
requestid = requests.request(
"POST",
"https://apiurl.com/apidataurlexample",
data=json.dumps(orderParams),
headers=headerData,
timeout=2 # expecting this to limit the freeze to 2 seconds
).json()
return requestid
except Exception as e:
print(e)
return 0
Here’s the traceback I received:
httplib_response = conn.getresponse()
^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3.11/http/client.py", line 1374, in getresponse
response.begin()
File "/usr/lib/python3.11/http/client.py", line 318, in begin
version, status, reason = self._read_status()
^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3.11/http/client.py", line 279, in _read_status
line = str(self.fp.readline(_MAXLINE + 1), "iso-8859-1")
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3.11/socket.py", line 706, in readinto
return self._sock.recv_into(b)
^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3.11/ssl.py", line 1311, in recv_into
return self.read(nbytes, buffer)
^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3.11/ssl.py", line 1167, in read
return self._sslobj.read(len, buffer)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TimeoutError: The read operation timed out
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/home/usernamehere/venv3/lib/python3.11/site-packages/requests/adapters.py", line 440, in send
resp = conn.urlopen(
^^^^^^^^^^^^^
File "/home/usernamehere/venv3/lib/python3.11/site-packages/urllib3/connectionpool.py", line 802, in urlopen
My questions:
Why is my function freezing if a timeout is explicitly defined?
Shouldn’t requests raise an exception or return after 2 seconds?
Could the new GCP server environment be responsible?
Is there a better way to enforce strict timeouts and prevent total freezes?
Any insights would be greatly appreciated.
I am unable to reproduce it, because I cannot run the code again today, since it is production code. Tomorrow, I will retry, but if the same error happens again, I am in BIG BIG TROUBLE. So I do not want this error to happen again!!
Edit: I am still getting some failed response from the API website like 10% of the time, the error says "Connection reset by peer". But this error is getting caught by my exception and it does not crash the program.
Edit: I am using Thread() to call this function like 20 times at once. Could this be the issue? My random guess is. One reason for this error could be that. The new GCP VM is very fast. So it might be able to run all the threads at once, and maybe two threads gave the same error at once, so it made the program to crash? Maybe there should be a gap of 0.00001 second between two thread error exceptions????
This is different "timeout", by setting timeout=2
you only handle requests
library timeout (requests.exceptions.Timeout
), but TimeoutError: The read operation timed out
is still not handled (it happens in libraries below requests).
Try this code:
requestid = requests.request(
"POST",
"https://apiurl.com/apidataurlexample",
data=json.dumps(orderParams),
headers=headerData,
timeout=(2, 2) # expecting this to limit the freeze to 2 seconds
).json()
From docs:
:param timeout: (optional) How many seconds to wait for the server to send data
before giving up, as a float, or a :ref:`(connect timeout, read
timeout) <timeouts>` tuple.