Как получить количество строк дешево в Python? - PullRequest
874 голосов
/ 10 мая 2009

Мне нужно получить количество строк большого файла (сотни тысяч строк) в Python. Как наиболее эффективно использовать память и время?

На данный момент я делаю:

def file_len(fname):
    with open(fname) as f:
        for i, l in enumerate(f):
            pass
    return i + 1

можно ли сделать что-нибудь лучше?

Ответы [ 37 ]

9 голосов
/ 15 октября 2014

ответ Кайла

num_lines = sum(1 for line in open('my_file.txt'))

, вероятно, лучше, альтернатива этому

num_lines =  len(open('my_file.txt').read().splitlines())

Вот сравнение производительности обоих

In [20]: timeit sum(1 for line in open('Charts.ipynb'))
100000 loops, best of 3: 9.79 µs per loop

In [21]: timeit len(open('Charts.ipynb').read().splitlines())
100000 loops, best of 3: 12 µs per loop
9 голосов
/ 06 января 2017

Однолинейное решение:

import os
os.system("wc -l  filename")  

Мой фрагмент:

>>> os.system('wc -l *.txt')

0 bar.txt
1000 command.txt
3 test_file.txt
1003 total
8 голосов
/ 03 апреля 2017

Однострочное решение bash, аналогичное этому ответу , с использованием современной функции subprocess.check_output:

def line_count(file):
    return int(subprocess.check_output('wc -l {}'.format(file), shell=True).split()[0])
8 голосов
/ 09 декабря 2016

Это самая быстрая вещь, которую я нашел, используя чистый питон. Вы можете использовать любой объем памяти, который вы хотите, установив буфер, хотя 2 ** 16 кажется приятным местом на моем компьютере.

from functools import partial

buffer=2**16
with open(myfile) as f:
        print sum(x.count('\n') for x in iter(partial(f.read,buffer), ''))

Я нашел ответ здесь Почему чтение строк из stdin в C ++ намного медленнее, чем в Python? и немного его подправило. Это очень хорошее чтение, чтобы понять, как быстро считать строки, хотя wc -l все еще примерно на 75% быстрее, чем что-либо еще.

7 голосов
/ 23 февраля 2015

Этот код короче и понятнее. Это, наверное, лучший способ:

num_lines = open('yourfile.ext').read().count('\n')
6 голосов
/ 05 мая 2010

Просто для завершения вышеуказанных методов я попробовал вариант с модулем fileinput:

import fileinput as fi   
def filecount(fname):
        for line in fi.input(fname):
            pass
        return fi.lineno()

И передал файл 60-миллиметровых строк всем вышеуказанным методам:

mapcount : 6.1331050396
simplecount : 4.588793993
opcount : 4.42918205261
filecount : 43.2780818939
bufcount : 0.170812129974

Меня немного удивляет, что входной файл настолько плох и масштабируется намного хуже, чем все другие методы ...

5 голосов
/ 21 марта 2014
print open('file.txt', 'r').read().count("\n") + 1
5 голосов
/ 10 мая 2009

На мой взгляд, этот вариант будет самым быстрым:

#!/usr/bin/env python

def main():
    f = open('filename')                  
    lines = 0
    buf_size = 1024 * 1024
    read_f = f.read # loop optimization

    buf = read_f(buf_size)
    while buf:
        lines += buf.count('\n')
        buf = read_f(buf_size)

    print lines

if __name__ == '__main__':
    main()

причины: буферизация быстрее, чем чтение построчно, а string.count также очень быстро

4 голосов
/ 25 ноября 2011

Я изменил регистр буфера следующим образом:

def CountLines(filename):
    f = open(filename)
    try:
        lines = 1
        buf_size = 1024 * 1024
        read_f = f.read # loop optimization
        buf = read_f(buf_size)

        # Empty file
        if not buf:
            return 0

        while buf:
            lines += buf.count('\n')
            buf = read_f(buf_size)

        return lines
    finally:
        f.close()

Теперь также учитываются пустые файлы и последняя строка (без \ n).

4 голосов
/ 17 сентября 2018

Простой метод:

num_lines = len(list(open('myfile.txt')))

...