For ... except ... finally

While using the instruction for on a generator, I wanted to catch an exception coming from the generator, and I didn’t found a better solution to use a verbose try except around the for, and which becomes complicated when several errors can come from both iteration and content codes.

Therefore, I would like to have this :

for i in generator:
    content()
except:  # executed when the iteration of *generator* or *content* raised an error
    pass. Might be defined several times as *try ... except* does
else:  # executed the for hasn't be interupted by an exception nor a break
    pass
finally: # executed after all above instructions
    pass

What do you think about this idea ?

It would help if you write what your current code looks like, but IIUC you have something like this

for i in range(10):
    try:
        <do stuff that might throw SomeException>
    except SomeException:
         <Handle exception and keep looping>

If you think that looks bad, I think the best way currently is to put the try-except in a function or use contextlib.supress

# I didn't run this code before so it might be buggy
from contextlib import suppress

for i in range(10):
    with suppress(SomeException):
        <do stuff that might throw SomeException>

I don’t think suppress can run any special code to handle the expection though so the full try-except would still be necessary in the general case.

I don’t dislike this idea but I also don’t think it’s worth it. The current way is alright and typically I only use try-except on the few lines that require it so I don’t feel like my entire loop body is a just a try-except statement.

I think you lose the ability to distinguish between break and an exception in exchange for dropping the try keyword and dedenting the loop. If you are concerned about exceptions raised by the generator, I would wrap it in another generator that can handle such exceptions separately from exceptions raised the body of the loop. Something like

def generator_cleaner():
    try:
        yield from generator
    except SomeError:
        ...
    else:
        ...
    finally:
        ...

Then you can put the try statement in the loop instead of wrapping the entire loop:

for i in generator_cleaner():
    try:
        content()
    except ...:
        ...
    else:
        ...
    finally:
        ...