exception raised by nested iterator being ignored by for loop

Bengt Richter bokr at oz.net
Sun Nov 20 06:56:54 CET 2005

On Sun, 20 Nov 2005 03:36:43 GMT, james t kirk <james.t.kirk at ussenterprise.com> wrote:

>I'm writing a wrapper class to handle the line merging and filtering
>for a log file analysis app
>The problem I'm running into is that the StopIteration exception
>raised when the wrapped file goes past EOF isn't causing the second
>for loop to stop. Wrapping the second for loop in a try/except clause
>shows that the exception is being raised though. 
>Could someone more familiar with the underlying implementation please
>give me a hint as to why this is happening?

>import gzip
>class wrapper :
>    def __init__ (self, filename) :
>        if filename[-3:] == ".gz" :
>            self.fh = gzip.GzipFile(filename, "r")
>        else :
>            self.fh = open(filename, "r")
>    def __iter__ (self) :
>        return self
>    def next (self) :
>        for line in self.fh :       # StopIteration raised here when
>file exhausted
Yes, but that just ends the for loop and that uses up the exception, so either
change the above "for ..." to two lines: (untested ;-/ )
         while True:
             line = self.fh.next()   # should raise StopIteration without
                                     # being caught by for
>            if line[:1] == "t" :    # filter out lines starting with
>                continue
>            return line.rstrip()
or otherwise the end of the for will catch the StopIteration and just drop out here.
Imagine you were just printing the line in the loop body instead of checking and
returning lines. With just a print, you wouldn't expect a StopIteration to escape the for loop, right?
If you want to leave the for unchanged, you could just tell the world that the wrapper iteration
is done, by using the following line here:
         raise StopIteration         # end of wrapper iteration

>if __name__ == "__main__" :
>    # using the file handle
>    fh = open("test.txt")
>    for line in fh :
>        print line.rstrip()
>    fh.close()
>    # using the wrapper class
>    fh = wrapper("test.txt")
>    for line in fh :                # StopIteration ignored here
>        print line

HTH (and that the untested code works ;-)

Bengt Richter

More information about the Python-list mailing list