Execution order with try-finally in python generator functions

137 Views Asked by At
def gen():
    try:
        yield 1
    finally:
        print("finally")


def main():
    print(next(gen()))

This code prints

finally
1

I don't understand the order of execution here. Why is "finally" printed before "1"?

3

There are 3 best solutions below

0
hynekcer On BEST ANSWER

You can rewrite the line print(next(gen())) as

g = gen()  # temporary variable
val = next(g)
#          # the generator is now deleted because the variable g is not referenced anymore
del(g)     # that calls the "finally" block `print("finally")`
print(val)

If you assign the generator to a variable, but don't delete it then it is recycled at the end of main function. That is what you probably expect.

A generator should be assigned to a variable if you use it by next(), otherwise there would be no way to use a generator with more items because it would be recycled after the first item!

0
msp729 On

The reason why "finally" is printed before "1" is because the first thing Python does is resolve next(gen()), which involves returning 1 and printing "finally". Once Python is done executing next(gen()), it has printed finally, and has a value of 1. Now, it can resolve print(1), which prints "1".

0
jack On

Here is an Example what is happening

  1. next(gen()) is executed -> gen() prints "finally" -> next() gets the value
  2. next() returns the value
  3. print() prints the value

You have to look here inside first and then the outer shell and the outer outer shell etc.