Search code examples
pythonpython-3.xlistcsvnested-loops

Unable to iterate "csv.reader" repeatedly - empty result on second iteration


I have created list1 to include the unique values from a particular column by appending values identified as unique to it in order to perform a sort of "sum if".

Below is the scenario I am struggling with, the inner loop, iterating through the csv rows is only executing once. Is there some special characteristic that makes iterating through rows in a csv file in the inner loop of a nested loop problematic?

csv contents:

Field1
row1
row2
row3

Code:

datafile = open(r"my_file.csv", "r")
myreader = csv.reader(datafile, delimiter=",")

list1 = ["A", "B", "C"]

for x in list1[:]:
    print(x)
        for y in myreader:
               print(y)

Expected result:

A
row1
row2
row3
B
row1
row2
row3
C
row1
row2
row3

Actual result:

A
row1
row2
row3<
B
C

It appears only the initial iteration of the inner loop is working.

If I replace the csv with another list it works fine:

datafile = open(r"my_file.csv", "r")
myreader = csv.reader(datafile, delimiter=",")

list1 = ["A", "B", "C"]
list2 = ["row1", "row2", "row2"]

for x in list2[:]:
    print(x)
        for y in list2:
               print(y)

gives expected result

And I can iterate through the csv rows in a single loop no problem with the below:

x = 0
for y in myreader:
        x = x + 1
        print(y[2] + " INNER")

So why won't it all work together?


Solution

  • csv.reader returns an reader object which is an iterator. So, once you iterate the entire list, it becomes empty. You need to save your reader as a list in order to iterate it repeatedly.

    In order to achieve this, you need to change:

    myreader = list(csv.reader(datafile, delimiter=","))
    #           ^ it'll save `myreader` as list
    

    Hence, you complete code should be:

    datafile = open(r"my_file.csv", "r")
    myreader = list(csv.reader(datafile, delimiter=","))    
    #           ^ converting the `iterator` to list type
    
    list1 = ["A", "B", "C"]
    
    #            v  I removed "[:]" from here because it is not required
    #            v  `list1[:]` creates a copy of the list "list1". You 
    #            v  don't need copy here
    for x in list1:
        print(x)
        for y in myreader:
            print(y)