RuntimeError raised for StopIteration on a for loop

Question:

I want to create an Iterator that runs a couple of checks and yield an object that follows all the checks, if no object is found, it raises a StopIteration to exit loops. Something similar to the code below:

def gen():
    for i in range(3):
        yield i

    raise StopIteration("Done")

for i in gen():
    print(i)

But when I run this I get the following output:

0
1
2
---------------------------------------------------------------------------
StopIteration                             Traceback (most recent call last)
<ipython-input-19-56228d701618> in gen()
      4 
----> 5     raise StopIteration("Done")

StopIteration: Done

The above exception was the direct cause of the following exception:

RuntimeError                              Traceback (most recent call last)
<ipython-input-20-a753ba4ac5a8> in <module>
----> 1 for i in gen():
      2     print(i)

I later change the code to exit in a different manner but this made me curious, doesn’t the for loop catch a StopIteration exception to finish the loop? Why would the code above result in such an error?

Asked By: João Areias

||

Answers:

The for loop does indeed catch the StopIteration exception to finish the loop. However, the StopIteration exception in the example you provided is raised after the for loop has already finished iterating. This means that the StopIteration exception is not caught by the for loop, and instead is raised as an unhandled exception, resulting in the RuntimeError you are seeing.

In order to achieve the behavior you want, you can wrap the for loop in a try-except block, and catch the StopIteration exception. In this way, you can handle the exception and exit the loop gracefully without raising an error.

Additionally, you can use a return statement instead of raise StopIteration to stop the execution of the generator function and it will inform the for loop to stop the iteration.

Answered By: Aditya Aggawral
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.