What happens when you 'break' a generator?

Frank Millman frank at chagford.com
Tue Jul 29 09:51:06 CEST 2014


"Peter Otten" <__peter__ at web.de> wrote in message 
news:lr7ilg$de4$1 at ger.gmane.org...
> Frank Millman wrote:
>
>> Hi all
>>
>> Python 3.4.1
>>
>> Here is a simple generator -
>>
>> def test():
>>     print('start')
>>     for i in range(5):
>>         yield i
>>     print('done')
>>
>> x = test()
>> for j in x:
>>     print(j)
>>
>> As expected, the output is -
>>
>> start
>> 0
>> 1
>> 2
>> 3
>> 4
>> done
>>
>> Here I break the loop -
>>
>> x = test()
>> for j in x:
>>     print(j)
>>     if j == 2:
>>         break
>>
>> Now the output is -
>>
>> start
>> 0
>> 1
>> 2
>>
>> 'done' does not appear, so the generator does not actually terminate. 
>> What
>> happens to it?
>>
>> My guess is that normal scoping rules apply. Using my example, the
>> generator is referenced by 'x', so when 'x' goes out of scope, the
>> generator is garbage collected, even though it never completed.
>>
>> Is this correct?
>
> Yes. In newer Pythons try...finally works, so you can see for yourself:
>
>>>> def f():
> ...     try:
> ...             for c in "abc": yield c
> ...     finally:
> ...             print("done")
> ...
>>>> g = f()
>>>> for c in g:
> ...     print(c)
> ...     if c == "b": break
> ...
> a
> b
>>>> del g
> done
>
> Also:
>
>>>> g = f()
>>>> next(g)
> 'a'
>>>> g.throw(GeneratorExit)
> done
> Traceback (most recent call last):
>  File "<stdin>", line 1, in <module>
>  File "<stdin>", line 3, in f
> GeneratorExit
>
>

Thanks for the clarification, Peter.

The subconscious does funny things. When I scanned your reply quickly, I 
could have sworn it said something about 'forcing a break'. When I read it 
more slowly, I could not find that. Then I realised it actually says 'for c 
in g' ...

Frank






More information about the Python-list mailing list