Best way to access the Nth line of csv file

Question:

I have to access the Nth line in a CSV file.

Here’s what I did:

import csv

the_file = open('path', 'r')
reader = csv.reader(the_file)

N = input('What line do you need? > ')
i = 0

for row in reader:
    if i == N:
        print("This is the line.")
        print(row)
        break

    i += 1

the_file.close()

…but this does not feel optimal. Edit for precision: If the file is huge, I do not want to go through all the lines and I do not want to have to load the whole file into memory.

I do hope something like reader[N] exists, but I have not found it.

Edit for answer: This line (coming from chosen answer) is what I was looking for:

next(itertools.islice(csv.reader(f), N, None)
Asked By: Gabriel L'Heureux

||

Answers:

You could minimize your for loop into a comprehension expression, e.g.

row = [row for i,row in enumerate(reader) if i == N][0]  

# or even nicer as seen in iCodez code with next and generator expression

row = next(row for i,row in enumerate(reader) if i == N)
Answered By: Marcin

Your solution is actually not that bad. Advancing the file iterator to the line you want is a good approach and is used in many situations like this.

If you want it more concise though, you can use next and enumerate with a generator expression:

import csv

the_file = open('path', 'r')
reader = csv.reader(the_file)

N = int(input('What line do you need? > '))

line = next((x for i, x in enumerate(reader) if i == N), None)
print(line)

the_file.close()

The None in there is what will be returned if the line is not found (N is too large). You can pick any other value though.


You could also open the file with a with-statement to have it be automatically closed:

import csv

with open('path', 'r') as the_file:
    reader = csv.reader(the_file)

    N = int(input('What line do you need? > '))

    line = next((x for i, x in enumerate(reader) if i == N), None)
    print(line)

If you really want to cut down on size, you could do:

from csv import reader
N = int(input('What line do you need? > '))
with open('path') as f:
    print(next((x for i, x in enumerate(reader(f)) if i == N), None))
Answered By: user2555451

You can use enumerate to iterate through the list until you find the right row:

for i, row in enumerate(reader):
    if i == line_number:
        print("This is the line.")
        print(row)
        break

You can also use itertools.islice which is designed for this type of scenario – accessing a particular slice of an iterable without reading the whole thing into memory. It should be a bit more efficient than looping through the unwanted rows.

def get_csv_line(path, line_number):
    with open(path) as f:
        return next(itertools.islice(csv.reader(f), line_number, None))

But if your CSV file is small, just read the entire thing into a list, which you can then access with an index in the normal way. This also has the advantage that you can access several different rows in random order without having to reset the csv reader.

with open(path) as f:
    my_csv_data = list(csv.reader(f))
print(my_csv_data[line_number])
Answered By: Stuart

You can simply do:

n = 2 # line to print
fd = open('foo.csv', 'r')
lines = fd.readlines()
print lines[n-1] # prints 2nd line
fd.close()

Or even better to utilize less memory by not loading entire file into memory:

import linecache
n = 2
linecache.getline('foo.csv', n)
Answered By: ajmartin
import csv
with open('cvs_file.csv', 'r') as inFile: 
    reader = csv.reader(inFile)
    my_content = list(reader)

line_no = input('What line do you need(line number begins from 0)? > ')
if line_no < len(my_content):
    print(my_content[line_no])
else:
    print('This line does not exists')

As a result now you can get any line by its index directly:

What line do you need? > 2
['101', '0.19', '1']

What line do you need? > 100
This line does not exists
Answered By: Tanveer Alam

The itertools module has a number of functions for creating specialized iterators — and its islice() function could be used to easily solve this problem:

import csv
import itertools

N = 5  # desired line number

with open('path.csv', newline='') as the_file:
    row = next(csv.reader(itertools.islice(the_file, N, N+1)))

print("This is the line.")
print(row)

P.S. For the curious, my initial response — which also works (arguably better) — was:

    row = next(itertools.islice(csv.reader(the_file), N, N+1))
Answered By: martineau
Categories: questions Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.