I would just like to understand, I'm using a Python script that sends 3 HTTP GET requests to an URL that I made to wait for 5 seconds.
I am using the requests library and the threading Python module like so:
#!/usr/bin/env python3
import time
import requests
from threading import Thread
url = 'https://mydebug-url.example.com/sleep/5'
payload = {}
def myfunc(i):
response = requests.get(url, json=payload)
print(f'Got back from {i} {response.status_code}. Response was {response.json()}')
if __name__ == '__main__':
start = time.time()
threads = []
for i in [1, 2, 3]:
thread = Thread(target=myfunc, args=[i])
threads.append(thread)
for thread in threads:
thread.start()
# Wait for all threads to finish
for thread in threads:
thread.join()
end = time.time()
print(f'took {end-start} seconds')
And the output is:
Got back from 2 200. Response was {'message': 'Slept 5 seconds'}
Got back from 1 200. Response was {'message': 'Slept 5 seconds'}
Got back from 3 200. Response was {'message': 'Slept 5 seconds'}
took 5.35151219367981 seconds
Now my question is, how is that efficient? So this code in the sample, using threading, takes a little more than 5 seconds so it's almost like doing them in parallel.
What puzzles me is, that it's kind of efficient, although:
- Python has GIL so it would have executed them in a single thread
- requests library is blocking (non async) so async wouldn't have worked either to benefit from one thread jumping rapidly between the 3 tasks while waiting.
So, what am I missing? where I can read more about it?
My interest is, I could use more of threading, still get the performance benefits, instead of changing to a async library to do requests, in case that is proven more difficult in the current codebase.
Thanks!