Alter each for-loop in a function to have error handling executed automatically after each failed iteration
Question: This question follows from [catch errors within generator and continue
afterwards](http://stackoverflow.com/questions/13645112/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.


Answer: I might "decorate" the functions themselves. Presumably you have them stored
in a list or something if you're living by DRY principles:

    
    
    def decorate_function(func):
        def decorated(x):
            try:
                return func(x)
            except Exception as e:
                log_error(e)
        return decorated
    

Now you can just decorate your functions with this and it will log your
errors. Note that this assumes that the `continue` statement above is
unnecessary. It looks like it isn't really used to me, but I might be missing
something.

If the functions really don't return something, then you could return `True`
or `False` depending on if you hit an exception. You could use that to write
your `continue` logic. Something like:

    
    
    if not decorated_function(x): continue
    

