holdtheline
holdtheline

Reputation: 103

Work on csv file - what's wrong with this simple code?

I'm new in python language and I'm trying to handle a csv file with this very simple test code:

import csv
csvfile= str(input("write file input name\n"))
read_file = open(csvfile)
file_in = csv.reader(read_file, delimiter=' ')
print("number of rows of",csvfile,"is:",len(list(file_in)))
i=1
for var in file_in :
    if i>1:
        print(var[1])
    i +=1
print("number of rows of",csvfile,"is:",len(list(file_in)))

giving this code a simple file "letters.csv" containing 7 rows like this:

a 2
b 7
c 9
d 11
e 3
f 9
g 96

what's strange for me is:

  1. why this code enter the for-loop and returns what I want only if I comment line 5 (print("number...)? Uncommenting line 5 the output is:
write file input name
letters.csv
number of rows of letters.csv is: 7
number of rows of letters.csv is: 0

commenting line 5 the output is:

write file input name
letters.csv
7
9
11
3
9
96
number of rows of letters.csv is: 0
  1. Why the expression in the last line (equal to line 5) returns always 0? Shouldn't be 7?

Upvotes: 0

Views: 68

Answers (3)

Booboo
Booboo

Reputation: 44013

file_in can only be iterated once. Your are trying to iterate it twice, the first time when you convert it to a list with list(file_in) and the second time when you execute the loop beginning for var in file_in :.

This can be corrected and a couple of improvements can be made. See the comments I have added to the code below. You should also study the PEP 8 -- Style Guide for Python Code:

import csv
#csvfile= str(input("write file input name\n"))
csvfile= input("write file input name\n") # the result of input is already a string
read_file = open(csvfile, newline='') # add newline argument
file_in = csv.reader(read_file, delimiter=' ')
print("number of rows of",csvfile,"is:",len(list(file_in)))
i=1
read_file.seek(0, 0) # position file back to the beginning
file_in = csv.reader(read_file, delimiter=' ') # create new iterator
i=0
for var in file_in :
    print(var)
    i +=1
print("number of rows of",csvfile,"is:", i)
close(read_file) # You should close your files

Upvotes: 1

ChrisOram
ChrisOram

Reputation: 1434

See the Python docs for the csv library reader function.

Return a reader object which will iterate over lines in the given csvfile.

You are exhausting the reader object in line 5 with list(file_in).

If you must find the length of the file before iterating through the reader object, you can produce a list first. Note that this will put the whole file into memory which becomes unwise when the csv file is very large.

import csv
csvfile = str(input("write file input name\n"))
read_file = open(csvfile)
file_in = csv.reader(read_file, delimiter=' ')
file_lines = list(file_in)
print("number of rows of", csvfile, "is:", len(file_lines))
i = 0
for line in file_lines:
    if i > 0:
        print(line[1])
    i += 1

Upvotes: 1

Krophil
Krophil

Reputation: 21

That's because file_in is a kind of iterator. When you read it in the for loop, you pop the lines one after the other.

Solution : don't use len(file_in) to get the length after a loop in it. Instead, make a list with datas or trust only file_in before looping in it

Upvotes: 0

Related Questions