Tuve que publicar esto en una pregunta similar hasta que mi puntaje de reputación aumentó un poco (¡gracias a quien me golpeó!).
Todas estas soluciones ignoran una forma de hacer que esto funcione considerablemente más rápido, es decir, usando la interfaz sin búfer (sin procesar), usando bytearrays y haciendo su propio almacenamiento en búfer. (Esto solo se aplica en Python 3. En Python 2, la interfaz en bruto puede o no usarse de manera predeterminada, pero en Python 3, usted usará Unicode de manera predeterminada).
Usando una versión modificada de la herramienta de sincronización, creo que el siguiente código es más rápido (y marginalmente más pitónico) que cualquiera de las soluciones ofrecidas:
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
Usando una función de generador separada, esto ejecuta un smidge más rápido:
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 )
Esto se puede hacer completamente con expresiones de generadores en línea usando itertools, pero se ve bastante extraño:
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 )
Aquí están mis horarios:
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