I'm answering an old question for future readers.
The finally
clause in a generator will be executed either when the interpreter reaches it while executing code inside the generator, or when the generator is finalized(deleted) if the interpreter didn't reached it while executing code inside the generator. You can read the reference.(See the paragraph starting with "Yield expressions are allowed anywhere".)
The following example demonstrates this.
def gen(name):
try:
yield None
print('after yield', name)
finally:
print('after finally', name)
g1 = gen('g1')
next(g1)
next(g1, None)
print('before del g1')
del g1
g2 = gen('g2')
next(g2)
print('before del g2')
del g2
This will output the following.
after yield g1
after finally g1
before del g1
before del g2
after finally g2
For the second question on the for
loop, I'll give an example.
for e in gen():
print(e)
The above code is equivalent to the following code.
iterator = gen()
while True:
try:
e = next(iterator)
except StopIteration:
break
print(e)
del iterator