Advanced Python Programming - Second Edition by Quan Nguyen

Advanced Python Programming - Second Edition by Quan Nguyen

Author:Quan Nguyen
Language: eng
Format: epub
Publisher: Packt Publishing Pvt. Ltd.
Published: 2022-02-21T00:00:00+00:00


Timeout specifications

Overall, an efficient ping test application should not be waiting for responses from its websites for a long time; it should have a set threshold for a timeout that, if a server fails to return a response under that threshold, the application will deem that server non-responsive. So, we need to implement a way to keep track of how much time has passed since a request has been sent to a server. We will do this by counting down from the timeout threshold. Once that threshold has been passed, all the responses (whether they've returned yet or not) will be printed out.

Additionally, we will also be keeping track of how many requests are still pending and have not had their responses returned. We will be using the is_alive() method from the threading.Thread class to indirectly determine whether a response has been returned for a specific request. If, at one point, the thread that's processing a specific request is alive, we can conclude that that specific request is still pending.

Let's consider the following process_requests() function first:

import time

UPDATE_INTERVAL = 0.01

def process_requests(threads, timeout=5):

def alive_count():

alive = [1 if thread.is_alive() else 0 for thread
in threads]

return sum(alive)

while alive_count() > 0 and timeout > 0:

timeout -= UPDATE_INTERVAL

time.sleep(UPDATE_INTERVAL)

for thread in threads:

print(thread.result)

This function takes in a list of threads that we have been using to make web requests in the previous examples, as well as an optional argument specifying the timeout threshold. Inside this function, we have an inner function, alive_count(), which returns the count of the threads that are still alive at the time of the function call.

In the process_requests() function, so long as there are threads that are currently alive and processing requests, we will allow the threads to continue with their execution (this is done in the while loop with the double condition). The UPDATE_INTERVAL variable, as you can see, specifies how often we check for this condition. If either condition fails (if there are no alive threads left or if the threshold timeout is passed), then we will proceed with printing out the responses (even if some might have not been returned).

Let's turn our attention to the new MyThread class:

import threading

import requests

class MyThread(threading.Thread):

def __init__(self, url):

threading.Thread.__init__(self)

self.url = url

self.result = f'{self.url}: Custom timeout'

def run(self):

res = requests.get(self.url)

self.result = f'{self.url}: {res.text}'

This class is almost identical to the one we considered in the previous example, except that the initial value for the result attribute is a message indicating a timeout. In the case that we discussed earlier, where the timeout threshold specified in the process_requests() function is passed, this initial value will be used when the responses are printed out.

Finally, let's consider our main program in example6.py:

urls = [

'http://httpstat.us/200',

'http://httpstat.us/200?sleep=4000',

'http://httpstat.us/200?sleep=20000',

'http://httpstat.us/400'

]

start = time.time()

threads = [MyThread(url) for url in urls]

for thread in threads:

thread.setDaemon(True)

thread.start()

process_requests(threads)

print(f'Took {time.time() - start : .2f} seconds')

print('Done.')

Here, in our URL list, we have a request that would take 4 seconds and another that would take 20 seconds, aside from the ones that would respond immediately.



Download



Copyright Disclaimer:
This site does not store any files on its server. We only index and link to content provided by other sites. Please contact the content providers to delete copyright contents if any and email us, we'll remove relevant links or contents immediately.