Milano
Milano

Reputation: 18745

Repeat an iteration in loop if error occurs

Is there a command such as break and continue which could repeat recent iteration?

For example, when exception is thrown.

for i in range(0,500):
    try:
        conn = getConnection(url+str(i))
        doSomething(conn)
    except:
        repeat

Let's have an iteration where i variable's value is 6. During this iteration some connection error occurred. I want to repeat this iteration.

Is there a command which can do that?

Of course I can do this:

i=0
while i!=500:
    try:
        conn = getConnection(url+str(i))
        doSomething(conn)
        i+=1
    except:
        pass

Upvotes: 25

Views: 38981

Answers (7)

Pedro Lobito
Pedro Lobito

Reputation: 99081

Here's a different approach that returns the function with arguments in case of exception:

retries = 0
max_retries = 5

def x(a, b):
  global retries
  global max_retries
  print(retries)
  try:
    d = a / b
  except:
    retries += 1
    if retries >= max_retries:
      return {}
    else:
      return x(a, b)

a = 0
b = 0
y = x(a, b)
print(y)

0
1
2
3
4
{}

Demo

Upvotes: 0

Dung Tran
Dung Tran

Reputation: 417

Here is one. You would need to add a logging or alert system to let you know that something is stuck:

state = "" #state of the loop

# If there is no error continue. If there is error, remain in loop
while True:
  if state != "error": 
    try:
      1/0 # command
      break # no error so break out of loop
    except:
      state = "error" #declare error so maintain loop
      continue
  elif state == "error": # maintain loop
    continue

Upvotes: 0

tdelaney
tdelaney

Reputation: 77407

You can use nested for loops to put a cap on the number of times you retry the operation. This is bascially the sam as @PierreAlex's generator answer but without the extra function definition.

for i in range(500):
    for retry in range(10):
        try:
            conn = getConnection(url+str(i))
            doSomething(conn)
        except Exception: # Replace Exception with something more specific.
            time.sleep(1)
    else:
        print "iteration", i, "failed"

Upvotes: 1

m.wasowski
m.wasowski

Reputation: 6386

for i in range(500):
    while True
        try:
            conn = getConnection(url+str(i))
            break
        except Exception: # still allows to quit with KeyboardInterrupt
            continue
    do_your_stuff()

This looks bit risky, however, you should at least enable some logging inside a while block.

If you expect to use it in more places, you might write a simple decorator:

def keep_trying(fn, *args, **kwargs):
    def inner(*args, **kwargs):
        while True:
            try:
                return fn(*args, **kwargs)
            except Exception:
                continue
    return inner

# later you can use it simple like this:
for i in range(500):
    conn = keep_trying(getConnection)(url+str(i))

Upvotes: 4

Pierre Alex
Pierre Alex

Reputation: 473

You can use generators :

def process_connections(n_connections, url, max_tries=50):
    i = 0
    try_count = 0
    while i < n_connections:
        try:
            conn = getConnection(url+str(i))
            yield conn
        except:
            try_count += 1
            if try_count > max_tries:
                raise Exception("Unable to connect after %s tries" % max_tries)
        else:
            i += 1 # increments only if no exception 

And you perform your operations :

for conn in process_connections(500, url):
    do_something(conn)

Upvotes: 2

user2555451
user2555451

Reputation:

No, there is no command to "rewind" a for-loop in Python.

You could use a while True: loop inside the for-loop:

for i in range(500):
    while True:
        try:
            conn = getConnection(url+str(i))
            doSomething(conn)
        except Exception: # Replace Exception with something more specific.
            continue
        else:
            break

or without the else::

for i in range(500):
    while True:
        try:
            conn = getConnection(url+str(i))
            doSomething(conn)
            break
        except Exception: # Replace Exception with something more specific.
            continue

But I personally think that your proposed solution is better because it avoids an indentation level.

Upvotes: 24

Why not just use an if statement?

n=6
i=0
while i!=500:
    failed = False;
    try:
        conn = getConnection(url+str(i))
        doSomething(conn)
        i+=1
    except:
        #handle error
        failed = True;

    #try again if n-th case failed first time
    if(i == n and failed):
        try:
            conn = getConnection(url+str(i))
            doSomething(conn)
        except:
            #handle error

Upvotes: 0

Related Questions