K1.
K1.

Reputation: 275

I get IndexError while still in the range

I am trying to read the rows of a csv file. My file looks like this

Col 1, Col 2, Col3
row11, row12, row13
row21, row22, row23
row31, row32, row33
...

I use the following command to read the rows

with open('~/data.csv') as f:
    r = csv.DictReader(f)
    for i in range(5):
        print(list(r)[i])

The output prints the first row, but then it give the out of index error right after.

IndexError                                Traceback (most recent call last)
<ipython-input-15-efcc4f8c760d> in <module>()
      2     r = csv.DictReader(f)
      3     for i in range(5):
----> 4         print(list(r)[i])

IndexError: list index out of range

I'm guessing I'm making a silly mistake somewhere, but can't spot it. Any ideas on what I am doing wrong and how to fix it?

EDIT: This is the output of print(list(r)):

[{'Col 1': 'row11', ' Col3': ' row13', ' Col 2': ' row12'}, {'Col 1': 'row21', ' Col3': ' row23', ' Col 2': ' row22'}, {'Col 1': 'row31', ' Col3': ' row33', ' Col 2': ' row32'}, {'Col 1': 'row41', ' Col3': ' row43', ' Col 2': ' row42'}, {'Col 1': 'row51', ' Col3': ' row53', ' Col 2': ' row52'}, {'Col 1': 'row61', ' Col3': ' row63', ' Col 2': ' row62'}, {'Col 1': 'row71', ' Col3': ' row73', ' Col 2': ' row72'}, {'Col 1': 'row81', ' Col3': ' row83', ' Col 2': ' row82'}, {'Col 1': 'row91', ' Col3': ' row93', ' Col 2': ' row92'}, {'Col 1': 'row101', ' Col3': ' row103', ' Col 2': ' row102'}]

Upvotes: 3

Views: 269

Answers (1)

jwilner
jwilner

Reputation: 6606

DictReader(f) just gives you a one time look at your file -- you can only call list on it once, but you call it multiple times because it's within the loop. Later calls return an empty list. Just call list on it outside of the loop and save it in a variable, and you'll be golden.

That is:

r = csv.DictReader(f)
rows = list(r)
for i in range(5):
    print(rows[i])

Or, don't pull the whole thing into memory at any point:

for row in csv.DictReader(f):
    print row

If you'd like to keep the index around for other purposes:

 for i, row in enumerate(csv.DictReader(f)):
     print i, row

If you want to get specific rows from an iterator (which csv.DictReader is a special case of) without pulling the whole thing into memory, check out itertools.islice at https://docs.python.org/3/library/itertools.html. It basically allows list-style slicing on an iterator.

  # prints first five rows
  for row in itertools.islice(csv.DictReader(f), 5):
       print row

For more sporadic rows:

  needed_row_indices = {2, 5, 20}
  for i, row in enumerate(csv.DictReader(f)):
      if i in needed_row_indices:
          print row

Upvotes: 5

Related Questions