Iterate through list and handle StopIteration in Python beautifully

Serge Tarkovski picture Serge Tarkovski · Jul 5, 2012 · Viewed 10.6k times · Source

I am trying to iterate through a list, and I need to perform specific operation when and only when the iteration reached the end of the list, see example below:

data = [1, 2, 3]

data_iter = data.__iter__()
try:
    while True:
        item = data_iter.next()
        try:
            do_stuff(item)
            break # we just need to do stuff with the first successful item
        except:
            handle_errors(item) # in case of no success, handle and skip to next item
except StopIteration:
    raise Exception("All items weren't successful")

I believe this code isn't too Pythonic, so I am looking for a better way. I think the ideal code should look like this hypothetical piece below:

data = [1, 2, 3]

for item in data:
    try:
        do_stuff(item)
        break # we just need to do stuff with the first successful item
    except:
        handle_errors(item) # in case of no success, handle and skip to next item
finally:
    raise Exception("All items weren't successful")

Any thoughts are welcome.

Answer

Andrew Clark picture Andrew Clark · Jul 5, 2012

You can use else after a for loop, and the code within that else is only executed if you did not break out of the for loop:

data = [1, 2, 3]

for item in data:
    try:
        do_stuff(item)
        break # we just need to do stuff with the first successful item
    except Exception:
        handle_errors(item) # in case of no success, handle and skip to next item
else:
    raise Exception("All items weren't successful")

You can find this in the documentation for the for statement, relevant pieces shown below:

for_stmt ::=  "for" target_list "in" expression_list ":" suite
              ["else" ":" suite]

A break statement executed in the first suite terminates the loop without executing the elseclause’s suite.