retry()
Retry a GET request a maximum of 5 times.
Let's assume you want to get some response from a get command. For all intensive purposes we will assume this is all happening inside a function called get_response(choice)
Next youy want to make a function try_again(response='pass')
that will keep trying to execute get_response(choice)
if we get a '401' response, which means that the client could not be authenticated. The catch is that we want the maximum retries to be 5 before accepting the failed authentication. Furthermore each time the retry function is called the function should sleep for n^2 seconds. It shouldn't wait anytime to execute the first get_response(choice)
, which is the one initially passed to try_again()
. Finally if we get '404' then return a '404 Not Found Error'.
We start by defining get_response()
def get_response(choice=3):
choices = {1:'404',2:'pass',3:'401'}
return choices[choice]
Now we need try_again(). I have to give credit to Zagaran which you can find a link to on the Sources tab for this algorithm. During an interview I attempted a recursive solution, but they said a for loop would of done. So for extra practice I implemented both.
def try_again_recursive(response, try_count=1):
"""
This function will take a response object
and do the following:
- If we get 'pass', return 'we connected!'
- If we get '404', return '404 Not Found Error'
- If we get '401', try again, however each time
you try again wait the square of the try
seconds before trying again. Try a maximum of 5
times before returning 'client could not be authenticated.'
Example:
try1: wait 1 seconds to retry
try2: wait 4 seconds to retry
try3: wait 9 seconds to retry
try4: wait 16 seconds to retry
try5: wait 0 seconds to retry! Since the max tries is 5,
there is no need to wait the additional 25 seconds
before exiting.
"""
if response == '404':
return '404 Not Found Error'
elif response == '401':
if try_count == 5:
print('for n = {0}, waiting {1} seconds.'.format(try_count, 0))
print('client could not be authenticated.')
else:
print('for n = {0}, waiting {1} seconds.'.format(try_count, try_count**2))
time.sleep(try_count**2)
try_again_recursive(get_response(), try_count=try_count+1)
else:
return 'we connected!'
return response
Check out the output below
# Tests
# >>>try_again_recursive(get_response())
# for n = 1, waiting 1 seconds.
# for n = 2, waiting 4 seconds.
# for n = 3, waiting 9 seconds.
# for n = 4, waiting 16 seconds.
# for n = 5, waiting 0 seconds.
# client could not be authenticated.
# '401'
One thing to note, I cheated a little. For the sake of practicing the multiple calls, I made sure the get_response() function always returned a '401'. We will address this a little later. For now let's implement the for loop version.
# For Loop Solution:
def try_again_for_loop(response):
"""
This function will take a response object
and do the following:
- If we get 'pass', return 'we connected!'
- If we get '404', return '404 Not Found Error'
- If we get '404', try again, however each time
you try again wait the square of the try
seconds before trying again. Try a maximum of 5
times before returning 'client could not be authenticated.'
Example:
try1: wait 1 seconds to retry
try2: wait 4 seconds to retry
try3: wait 9 seconds to retry
try4: wait 16 seconds to retry
try5: wait 0 seconds to retry! Since the max tries is 5,
there is no need to wait the additional 25 seconds
before exiting.
"""
for i in range(1,6): # [1,2,3,4,5]
if response == '404':
return '404 Not Found Error'
elif response == '401':
if i == 5:
print('for n = {0}, waiting {1} seconds.'.format(i, 0))
print('client could not be authenticated.')
else:
# pdb.set_trace()
print('for n = {0}, waiting {1} seconds.'.format(i, i**2))
time.sleep(i**2)
response = get_response()
else:
return 'we connected!'
return response
Output:
# >>> try_again_for_loop(get_response())
# for n = 1, waiting 1 seconds.
# for n = 2, waiting 4 seconds.
# for n = 3, waiting 9 seconds.
# for n = 4, waiting 16 seconds.
# for n = 5, waiting 0 seconds.
# client could not be authenticated.
# '401'
Now we need to simulate reality a little better to give the other logic a chance to be executed. Let's make it so get_response() could return any of the other values ('pass','404').
Go into the recursive version of try_again()
and find this line try_again_recursive(get_response(), try_count=try_count+1)
, and change it to try_again_recursive(get_response(random.randint(1,3)), try_count=try_count+1)
. You will need to import random
at the top of your script. Then also add to your call of try_again_recursive()
Results:
# Simulation
# >>> try_again_recursive(get_response(random.randint(1,3)))
# for n = 1, waiting 1 seconds.
# '401'
# >>> try_again_recursive(get_response(random.randint(1,3)))
# for n = 1, waiting 1 seconds.
# '401'
# >>> try_again_recursive(get_response(random.randint(1,3)))
# 'we connected!'
# >>> try_again_recursive(get_response(random.randint(1,3)))
# for n = 1, waiting 1 seconds.
# '401'
# >>> try_again_recursive(get_response(random.randint(1,3)))
# '404 Not Found Error'
# >>> try_again_recursive(get_response(random.randint(1,3)))
# for n = 1, waiting 1 seconds.
# for n = 2, waiting 4 seconds.
# for n = 3, waiting 9 seconds.
# for n = 4, waiting 16 seconds.
# for n = 5, waiting 0 seconds.
# client could not be authenticated.
# '401'
Again, the for loop version changes the same thing, ie. response = get_response(
to this response = get_response(random.rendint(1,3))
.
# >>> try_again_for_loop(get_response(random.randint(1,3)))
# for n = 1, waiting 1 seconds.
# for n = 2, waiting 4 seconds.
# '404 Not Found Error'
# >>> try_again_for_loop(get_response(random.randint(1,3)))
# for n = 1, waiting 1 seconds.
# for n = 2, waiting 4 seconds.
# for n = 3, waiting 9 seconds.
# 'we connected!'
# >>> try_again_for_loop(get_response(random.randint(1,3)))
# for n = 1, waiting 1 seconds.
# for n = 2, waiting 4 seconds.
# for n = 3, waiting 9 seconds.
# 'we connected!'
# >>> try_again_for_loop(get_response(random.randint(1,3)))
# '404 Not Found Error'