4

I have got the following piece of code, so that while any exception occurs, re-do this loop, instead of jumping to the next loop. Please note the pseudo code here does work as intended:

for cl in range(0, 10):
    try:
        some_function(cl)
    except :
        cl -= 1

My initiative was that once something go wrong, do it again. Obviously, this is not a working idea. So given the assumption that the for loop and range function being used, how to implement the control that I described?

Thanks

3
  • Are you sure that some_function() will eventually succeed? Because otherwise, you will have an infinite loop. Commented Dec 13, 2012 at 23:22
  • @KyleStrand No, not sure. But outside of this code, there is a timer to ping an alert program at a frequent rate, once it has not get pinged for a timeout period of time, it will shoot an alert. For simplicity, I didn't mentioned. But thanks all the same for pointing out that. Commented Dec 13, 2012 at 23:32
  • It's a really bad sign you are iterating over a range. Do you actually want numbers or are you using them as indices, if it's the latter, it's not Pythonic and there is a better way. Likewise, except should only be used with specific exceptions, as otherwise you are likely to catch things you don't mean to and obscure bugs. Commented Dec 13, 2012 at 23:46

3 Answers 3

6

You simply need a second loop inside the first to continue trying the function until it works:

for cl in range(0, 10):
    while True:
        try:
            some_function(cl)
        except Exception:
            continue    # try it again
        else:
            break       # exit inner loop, continue to next c1
Sign up to request clarification or add additional context in comments.

7 Comments

I much prefer this since it also works with "real" Python for loops that iterate over a sequence of objects directly.
Agreed. Also, if, upon failure, some_function() merely returned False instead of throwing an exception, you could simplify this code and replace the while True: with the line while not some_function(cl): pass.
@kindall Out of curiosity, is it redundant to have that 'else' keyword? Why not directly break?
I like being explicit, but you could indeed break after the try/except, or even inside the try block itself, after the function call.
I believe it's not redundant in this case, but it would not be redundant if the except clause didn't force a continue.
|
4

For more control over the loop variable, you might want to use a while loop:

cl = 0
while cl < 10:
    try:
        some_function(cl)
        cl += 1
    except:
        pass

In Python, the pass statement is a "do-nothing" placeholder. In the case where you get an exception, the same cl value will be tried again.

Of course, you will also want to add some mechanism where you can exit the loop if you always get an exception.

4 Comments

I know this is demo code, but you should also encourage catching specific exception types. Other than that, great post.
@ThaneBrimhall: That's a good point. Catching all exceptions with except: makes it difficult to exit the program with Ctrl+C.
@GregHewgill: Nope, KeyboardInterrupt isn't caught by a bare except: because it inherits from BaseException directly.
@TimPietzcker: Good to know, thanks. I know I've run into that problem before, but it must have been for a different reason.
2

Because I have a pathological hatred of while True loops, I suggest this simplification of @kindall's answer: first, change some_function() so that it returns False on failure instead of throwing an exception. Then, use the following loop:

for cl in range(0, 10):
    while not some_function(cl): pass

If you can't (or don't want to) change some_function(), you could add a wrapper:

def exceptionless_function(arg):
    try:
        some_function(arg)
        return True
    except <known exceptions>:
        return False

EDIT: I added <known exceptions> above to indicate that the unqualified except clause should be avoided. If you don't know what types of exceptions you actually expect to catch, then simply calling the function again is almost certainly the wrong behavior in certain cases. For instance, OP mentions (in a comment) that there will be "an alert" if a timeout occurs while this function is being retried. If that alert happens to take the form of some kind of exception, then it will simply be ignored in the "catch-all" case!

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.