JF Stackhouse
JF Stackhouse

Reputation: 23

Why is this for loop not called if there are any preceding statements? (Python 2.7)

Reading a csv, I find I'm unable to iterate through rows if there are any preceding statements in my with block.

For example, if I do this:

with open (TargetFile) as source:
        Strings = csv.reader(source)
        for row in Strings:
            print Strings.line_num 

I'll get the integers 1 - (# of rows) printed to console. (Useless, yes, but I'm just testing the for with something obvious.)

However, say I'm looking to grab a row at random. I'd want to first determine the # of rows and generate a random number within that range, then iterate through the rows in search of a matching line_num.

(Here, I've kept the useless print Strings.line_num to avoid introducing new mistakes to the mix.)

    with open (TargetFile) as source:
        Strings = csv.reader(source)       
        CSV_Length = sum(1 for row in Strings)
        print CSV_Length
        RandRow = random.randrange(1,CSV_Length)
        print RandRow
        for row in Strings:
            print Strings.line_num
            #replace ^ with actually useful code

Will print the number of rows in the csv file and a random integer in that range to the console - all as expected - but the (previously working) for loop won't be called. Without that loop, I can't get to the useful and interesting bit

What am I missing, here?

Upvotes: 2

Views: 46

Answers (2)

TheBlackCat
TheBlackCat

Reputation: 10308

As Daniel said, the problem is that you are iterating over lines in the file. The proper solution, however, is to rewind the file:

Source.seek(0, 0)

This will put you back at the beginning of the file.

Upvotes: 0

Daniel Roseman
Daniel Roseman

Reputation: 599778

You're missing that Strings is an iterator. Once you iterate it to get the length, it is exhausted. So the for loop now has nothing to operate on.

You could fix this by converting to a list straight away:

strings = list(csv.reader(source))

Having done this, you could now access len(strings) to get the length anyway.

Upvotes: 1

Related Questions