Q:

Alter each for-loop in a function to have error handling executed automatically after each failed iteration

This question follows from catch errors within generator and continue afterwards
I have about 50 similar (but different) functions which try to extract URLs and such from websites. Because each website is different, each function is different and because websites tend to change over time this code is messy and cannot be trusted.
Here's a simplified sample, or look at the sample in the first question
def _get_units(self):
    for list1 in self.get_list1():
        for list2 in self.get_list2(list1):
            for unit in list2:
                yield unit

What I want to do with this function is essentially change the behavior to match this:
def _get_units(self):
    for list1 in self.get_list1():
        try:                 
            for list2 in self.get_list2(list1):
                try:
                    for unit in list2:
                        try:
                            yield unit
                        except Exception as e:
                            log_exception(e)
                except Exception as e:
                    log_exception(e)
        except Exception as e:
            log_exception(e)

In short, I want to turn this
for x in list:
    do_stuff(x)

to this:
for x in list:
    try:
        do_stuff(x)
    except Exception as e:
        log_exception(e)

for each for in my functions.
But I want to do it in a pythonic way. I don't want try:except blocks scattered all over the 50 functions I need to alter. Is this possible? If so, how can I do it in the most DRY way, and can I do this with the error handling in one place?
UPDATE: this question formerly included a continue statement along with the logging, but as mgilson pointed out, this isn't necessary.
UPDATE 2 with georgesl's answer the function becomes as follows:
from contextlib import contextmanager

@contextmanager
def ErrorManaged():
    try:
        yield
    except Exception as e:
        log_exception(e)

def _get_units(self):
    for list1 in self.get_list1():
        with ErrorManaged():              
            for list2 in self.get_list2(list1):
                with ErrorManaged():
                    for unit in list2:
                        with ErrorManaged():
                            yield unit

which is a lot cleaner indeed. though, a mere decorator would be even better. can anyone tell me if this is possible? if not, i'll accept georgesl's answer.

A:

You might want to use decorators or better, the context manager :
from contextlib import contextmanager

def HandleError(func):

    def wrapped(*args, **kwargs):

        try:
            func(*args, **kwargs)
        except Exception:
            print "Bug on node #", args[0]

    return wrapped

@contextmanager
def ErrorManaged():
    try:
        yield
    except Exception:
        print "Oh noes, the loop crashed"

@HandleError
def do_something(x):
    print x
    if x==5:
        raise('Boom !')

with ErrorManaged():
    for x in range(10):
        do_something(x)
        if x == 7 :
            raise('aaaah !')

A:

I gave this some more thought, the only solution to really suit my needs seems to be to modify the code itself. So here goes:
from contextlib import contextmanager
import inspect

@contextmanager
def ErrorManaged():
    try:
        yield
    except Exception as e:
        print e

def get_units():
    for x in range(-5,5):
        print(x)

        if x % 3 == 0:
            raise Exception("x nope")

        for y in range(-5,5):
            print("\t{}".format(y))

            if y % 3 == 0:
            raise Exception("y nope")

            for z in range(-5,5):
                print("\t\t{}".format(z))

                if z % 3 == 0:
                    raise Exception("z nope")

import re

def modify_get_units(get_units):    
    lines = inspect.getsourcelines(get_units)[0]
    add = "with ErrorManaged():\n"
    new = []
    tabsize = 0
    for c in lines[1]:
        if c == " ":
            tabsize += 1
        else:
            break

    count = 0
    for line in lines:
        new.append(" " * tabsize * count + line)
        m = re.match(r"^(\s+)for\s[()\w,]+\sin\s[^ :\n]+:\n$",line)
        if m:
            count += 1
            new.append(m.group(1) + " " * tabsize * count + add)

    return "".join(new)

oldfunc = inspect.getsource(get_units)
newfunc = modify_get_units(get_units)

#printing function bodies to show results

print(oldfunc)
print("\n\n\n")
print(newfunc)

#re-declare get_units
exec newfunc

#execute, but now now
#get_units()

output:
toon@ToonAlfrinkPC ~ $ python test.py
def get_units():
    for x in range(-5,5):
        print(x)

        if x % 3 == 0:
            raise Exception("x nope")

        for y in range(-5,5):
            print("\t{}".format(y))

            if y % 3 == 0:
                raise Exception("y nope")

            for z in range(-5,5):
                print("\t\t{}".format(z))

                if z % 3 == 0:
                    raise Exception("z nope")

def get_units():
    for x in range(-5,5):
        with ErrorManaged():
            print(x)

            if x % 3 == 0:
                raise Exception("x nope")

            for y in range(-5,5):
                with ErrorManaged():
                    print("\t{}".format(y))

                    if y % 3 == 0:
                        raise Exception("y nope")

                    for z in range(-5,5):
                        with ErrorManaged():
                            print("\t\t{}".format(z))

                            if z % 3 == 0:
                                raise Exception("z nope")

Thanks for helping me get there!

