'How to detect generator end explicitly in Python?

I wrote a generator, which returns tuple of values:

import numpy as np

def mygenerator():
    data = np.arange(10)
    data = np.reshape(data, (-1, 2))
    for row in data:
        yield row[0], row[1]

generator = mygenerator()
while True:
    a, b = generator.__next__()
    print("a: ", a, "b: ", b)

and want to use it without for ... in. How detect end of generation then?



Solution 1:[1]

The generator will throw an exception StopIteration when it is exhausted. You can catch the exception with tryexcept statement and exit loop when it occurs:

while True:
    try:
        a, b = next(generator)
    except StopIteration:
        break
    print("a: ", a, "b: ", b)

BTW, why not for loop? It seems that:

for a, b in generator:
    print("a: ", a, "b: ", b)

does exactly what you want, without cumbersome constructions.

Solution 2:[2]

Another possibility would be by using the default parameter of next built-in function as a breaking condition. Once the generator is exhausted, instead of throwing a StopIteration exception, the default value will be emitted.

# ...

gen = mygenerator()

stop_value = None # or another value
while True:
    v = next(gen, stop_value)
    if v is stop_value:
        break
    print("a: {}, b: {}".format(*v))

Solution 3:[3]

Stumped into this and suggest do following, generator will exhaust until next() returns None:

import numpy as np

def mygenerator():
    data = np.arange(10)
    data = np.reshape(data, (-1, 2))
    for row in data:
        yield row[0], row[1]

generator = mygenerator()
a, b = next(generator, None)
while a and b:
    print("a: ", a, "b: ", b)
    a, b = next(generator, None)

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Błotosmętek
Solution 2 cards
Solution 3 Greenonline