Ho dovuto postare questo su una domanda simile fino a quando il mio punteggio di reputazione è saltato un po '(grazie a chiunque mi abbia urtato!).
Tutte queste soluzioni ignorano un modo per rendere questa corsa considerevolmente più veloce, vale a dire usando l'interfaccia senza buffer (raw), usando i bytearrays e facendo il tuo buffering. (Ciò si applica solo in Python 3. In Python 2, l'interfaccia non elaborata può essere utilizzata o meno per impostazione predefinita, ma in Python 3, verrà impostato automaticamente Unicode.)
Utilizzando una versione modificata dello strumento di cronometraggio, credo che il seguente codice sia più veloce (e marginalmente più pitonico) di qualsiasi delle soluzioni offerte:
def rawcount(filename):
f = open(filename, 'rb')
lines = 0
buf_size = 1024 * 1024
read_f = f.raw.read
buf = read_f(buf_size)
while buf:
lines += buf.count(b'\n')
buf = read_f(buf_size)
return lines
Utilizzando una funzione di generatore separata, questo fa funzionare un fumo più velocemente:
def _make_gen(reader):
b = reader(1024 * 1024)
while b:
yield b
b = reader(1024*1024)
def rawgencount(filename):
f = open(filename, 'rb')
f_gen = _make_gen(f.raw.read)
return sum( buf.count(b'\n') for buf in f_gen )
Questo può essere fatto completamente con le espressioni dei generatori in linea usando itertools, ma diventa piuttosto strano:
from itertools import (takewhile,repeat)
def rawincount(filename):
f = open(filename, 'rb')
bufgen = takewhile(lambda x: x, (f.raw.read(1024*1024) for _ in repeat(None)))
return sum( buf.count(b'\n') for buf in bufgen )
Ecco i miei tempi:
function average, s min, s ratio
rawincount 0.0043 0.0041 1.00
rawgencount 0.0044 0.0042 1.01
rawcount 0.0048 0.0045 1.09
bufcount 0.008 0.0068 1.64
wccount 0.01 0.0097 2.35
itercount 0.014 0.014 3.41
opcount 0.02 0.02 4.83
kylecount 0.021 0.021 5.05
simplecount 0.022 0.022 5.25
mapcount 0.037 0.031 7.46