Как получить количество строк дешево в Python?

При переопределении метода Equals вам необходимо переопределить GetHashCode. Дополнительное объяснение можно найти здесь:

Почему важно переопределить GetHashCode, когда метод Equals переопределен?

880
задан SilentGhost 10 May 2009 в 10:22
поделиться

11 ответов

Вы не можете найти ничего лучше этого.

В конце концов, любое решение должно будет прочитать весь файл, выяснить, сколько \ n у вас есть , и вернуть результат.

Есть ли у вас лучший способ сделать это, не читая файл целиком? Не уверен ... Лучшее решение всегда будет с привязкой к вводу-выводу, лучшее, что вы можете сделать, это убедиться, что вы не используете ненужную память, но похоже, что у вас это покрыто.

335
ответ дан 19 December 2019 в 20:21
поделиться

результатом открытия файла является итератор, который можно преобразовать в последовательность, имеющую длину:

with open(filename) as f:
   return len(list(f))

это более кратко, чем ваш явный цикл, и позволяет избежать перечисление .

1
ответ дан 19 December 2019 в 20:21
поделиться
def file_len(full_path):
  """ Count number of lines in a file."""
  f = open(full_path)
  nr_of_lines = sum(1 for line in f)
  f.close()
  return nr_of_lines
10
ответ дан 19 December 2019 в 20:21
поделиться

Вы можете выполнить подпроцесс и запустить wc -l filename

import subprocess

def file_len(fname):
    p = subprocess.Popen(['wc', '-l', fname], stdout=subprocess.PIPE, 
                                              stderr=subprocess.PIPE)
    result, err = p.communicate()
    if p.returncode != 0:
        raise IOError(err)
    return int(result.strip().split()[0])
85
ответ дан 19 December 2019 в 20:21
поделиться

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

#!/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 тоже очень быстрая

5
ответ дан 19 December 2019 в 20:21
поделиться

Как насчет этого

def file_len(fname):
  counts = itertools.count()
  with open(fname) as f: 
    for _ in f: counts.next()
  return counts.next()
3
ответ дан 19 December 2019 в 20:21
поделиться

Я считаю, что файл с отображением памяти будет самым быстрым решением. Я пробовал четыре функции: функцию, отправленную OP ( opcount ); простой перебор строк в файле ( simplecount ); строка чтения с отображенным в память полем (mmap) ( mapcount ); и решение для чтения из буфера, предложенное Николаем Харечко ( bufcount ).

Я запускал каждую функцию пять раз и рассчитал среднее время выполнения для текстового файла с 1,2 млн строк.

Windows XP , Python 2.5, 2 ГБ ОЗУ, процессор AMD 2 ГГц

Вот мои результаты:

mapcount : 0.465599966049
simplecount : 0.756399965286
bufcount : 0.546800041199
opcount : 0.718600034714

Изменить : числа для Python 2.6:

mapcount : 0.471799945831
simplecount : 0.634400033951
bufcount : 0.468800067902
opcount : 0.602999973297

Таким образом, стратегия чтения из буфера кажется самой быстрой для Windows / Python 2.6

Вот код:

from __future__ import with_statement
import time
import mmap
import random
from collections import defaultdict

def mapcount(filename):
    f = open(filename, "r+")
    buf = mmap.mmap(f.fileno(), 0)
    lines = 0
    readline = buf.readline
    while readline():
        lines += 1
    return lines

def simplecount(filename):
    lines = 0
    for line in open(filename):
        lines += 1
    return lines

def bufcount(filename):
    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)

    return lines

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


counts = defaultdict(list)

for i in range(5):
    for func in [mapcount, simplecount, bufcount, opcount]:
        start_time = time.time()
        assert func("big_file.txt") == 1209138
        counts[func].append(time.time() - start_time)

for key, vals in counts.items():
    print key.__name__, ":", sum(vals) / float(len(vals))
193
ответ дан 19 December 2019 в 20:21
поделиться

Одна строка, вероятно, довольно быстрая:

num_lines = sum(1 for line in open('myfile.txt'))
582
ответ дан 19 December 2019 в 20:21
поделиться

Чтобы завершить описанные выше методы, я попробовал вариант с модулем 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

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

6
ответ дан 19 December 2019 в 20:21
поделиться

Почему бы не прочитать первые 100 и последние 100 строк и оценить среднюю длину строки, а затем разделить общий размер файла на эти числа? Если вам не нужно точное значение, это может сработать.

-1
ответ дан 19 December 2019 в 20:21
поделиться

что насчет этого?

import sys
sys.stdin=open('fname','r')
data=sys.stdin.readlines()
print "counted",len(data),"lines"
-1
ответ дан 19 December 2019 в 20:21
поделиться
Другие вопросы по тегам:

Похожие вопросы: