Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In Python try until no error

People also ask

How do you use try without except in Python?

We cannot have the try block without except so, the only thing we can do is try to ignore the raised exception so that the code does not go the except block and specify the pass statement in the except block as shown earlier. The pass statement is equivalent to an empty line of code. We can also use the finally block.

Does Python continue after try except?

finally ..." in Python. In Python, try and except are used to handle exceptions (= errors detected during execution). With try and except , even if an exception occurs, the process continues without terminating.

Is it good to use try except Python?

The reason to use try/except is when you have a code block to execute that will sometimes run correctly and sometimes not, depending on conditions you can't foresee at the time you're writing the code.

How do I stop Python from closing after error?

You need to modify your python application to catch the exception and print it without exiting the interpreter. One way to do that is to print "press ENTER to exit" and then read some input from the console window, effectively waiting for the user to press Enter.


It won't get much cleaner. This is not a very clean thing to do. At best (which would be more readable anyway, since the condition for the break is up there with the while), you could create a variable result = None and loop while it is None. You should also adjust the variables and you can replace continue with the semantically perhaps correct pass (you don't care if an error occurs, you just want to ignore it) and drop the break - this also gets the rest of the code, which only executes once, out of the loop. Also note that bare except: clauses are evil for reasons given in the documentation.

Example incorporating all of the above:

result = None
while result is None:
    try:
        # connect
        result = get_data(...)
    except:
         pass
# other code that uses result but is not involved in getting it

Here is one that hard fails after 4 attempts, and waits 2 seconds between attempts. Change as you wish to get what you want form this one:

from time import sleep

for x in range(0, 4):  # try 4 times
    try:
        # msg.send()
        # put your logic here
        str_error = None
    except Exception as str_error:
        pass

    if str_error:
        sleep(2)  # wait for 2 seconds before trying to fetch the data again
    else:
        break

Here is an example with backoff:

from time import sleep

sleep_time = 2
num_retries = 4
for x in range(0, num_retries):  
    try:
        # put your logic here
        str_error = None
    except Exception as str_error:
        pass

    if str_error:
        sleep(sleep_time)  # wait before trying to fetch the data again
        sleep_time *= 2  # Implement your backoff algorithm here i.e. exponential backoff
    else:
        break

Maybe something like this:

connected = False

while not connected:
    try:
        try_connect()
        connected = True
    except ...:
        pass

When retrying due to error, you should always:

  • implement a retry limit, or you may get blocked on an infinite loop
  • implement a delay, or you'll hammer resources too hard, such as your CPU or the already distressed remote server

A simple generic way to solve this problem while covering those concerns would be to use the backoff library. A basic example:

import backoff

@backoff.on_exception(
    backoff.expo,
    MyException,
    max_tries=5
)
def make_request(self, data):
    # do the request

This code wraps make_request with a decorator which implements the retry logic. We retry whenever our specific error MyException occurs, with a limit of 5 retries. Exponential backoff is a good idea in this context to help minimize the additional burden our retries place on the remote server.


The itertools.iter_except recipes encapsulates this idea of "calling a function repeatedly until an exception is raised". It is similar to the accepted answer, but the recipe gives an iterator instead.

From the recipes:

def iter_except(func, exception, first=None):
    """ Call a function repeatedly until an exception is raised."""
    try:
        if first is not None:
            yield first()            # For database APIs needing an initial cast to db.first()
        while True:
            yield func()
    except exception:
        pass

You can certainly implement the latter code directly. For convenience, I use a separate library, more_itertools, that implements this recipe for us (optional).

Code

import more_itertools as mit

list(mit.iter_except([0, 1, 2].pop, IndexError))
# [2, 1, 0]

Details

Here the pop method (or given function) is called for every iteration of the list object until an IndexError is raised.

For your case, given some connect_function and expected error, you can make an iterator that calls the function repeatedly until an exception is raised, e.g.

mit.iter_except(connect_function, ConnectionError)

At this point, treat it as any other iterator by looping over it or calling next().