2

How could I go about doing something like this

  1. Try to do something.
  2. If it works, great, continue with normal flow.
  3. If it fails run a function and try again.
  4. If it once again fails throw an exception and stop code.

I believe I would have to make use of try but I haven't quite come around yet to how to use it in this particular example.

2
  • Does the "something" you want to try have a chance of throwing an exception? If it doesn't, or it doesn't have to, then by all means avoid using try as a means of program flow. Commented Aug 16, 2015 at 22:02
  • Yep it does. Basically something() is a file-altering operation that, if the file doesn't exist, will blow up. The later mentioned afunction() is a file-searching function to correct the file's name so something() will run correctly. Commented Aug 16, 2015 at 22:04

4 Answers 4

5

It doesn't sound like you want to do a nested try-catch at all. Exceptions as control flow are a gnarly anti-pattern, and where you can avoid it, you should.

In this scenario, avoidance is easy. In the method that you describe, you want to be sure that a file exists before you do some operations on it. You also have a method to "correct" the path should it not. If both attempts fail, then you want to bail out.

With that into account, we would want to use os.path.isfile for this.

from os.path import isfile

def something(filepath):
    # Don't mutate the parameter if you can help it.
    p = filepath
    if not isfile(p):
        p = correct_path(p)
        if not isfile(p):
            raise Error("Cannot find file {} after correction to {}, aborting.".format(filepath, p))
    with open(p, 'r') as f:
        # Rest of file operations here
Sign up to request clarification or add additional context in comments.

Comments

3

This works for an arbitrary number of tries; I set it to two since that's what you want.

tries = 2
while True:
    try:
        step1()
    except CatchThisException:
        tries -= 1
        if tries:  # if tries != 0
            step3()
            continue  # not necessary, just for clarity
        else:
            raise  # step 4
    else:
        break  # step 2

Comments

2

Try a nested try catch:

try:
    do_something() #if this works, will skip rest and continue
except:
    do_fix_function() #on error, do extra function
    try:
        do_something() #try again
    except:
        throw error() #if it fails this time, stop and throw an error

Note that if your do_fix_function() can also fail, you might want to put it inside the second try statement instead

Comments

-1

You can use retrying package to solve your retry attempt. Just write a block of code that keeps repeating on failure, until max retries is hit

For example:

import random from retrying import retry

@retry
def do_something_unreliable():
    if random.randint(0, 10) > 1:
        raise IOError("Broken sauce, everything is hosed!!!111one")
    else:
        return "Awesome sauce!"

print do_something_unreliable()

1 Comment

This answer does not work. @retry does not allow for a “fix” function to be run between retries (unless you do hacky side effects). The OP also only wants to retry once (which is possible, but not done in this answer). @retry is for flaky functions, not deterministic failures. I suggest that next time you read the question more carefully before rushing to judgement and an answer.

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.