Ich musste dies auf eine ähnliche Frage posten, bis mein Reputationswert ein wenig sprang (danke an jeden, der mich gestoßen hat!).
Alle diese Lösungen ignorieren eine Möglichkeit, diesen Lauf erheblich zu beschleunigen, nämlich die Verwendung der ungepufferten (Roh-) Schnittstelle, die Verwendung von Bytearrays und die eigene Pufferung. (Dies gilt nur in Python 3. In Python 2 wird die Rohschnittstelle möglicherweise standardmäßig verwendet oder nicht, in Python 3 wird jedoch standardmäßig Unicode verwendet.)
Unter Verwendung einer modifizierten Version des Timing-Tools ist der folgende Code meiner Meinung nach schneller (und geringfügig pythonischer) als jede der angebotenen Lösungen:
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
Mit einer separaten Generatorfunktion wird ein Smidge schneller ausgeführt:
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 )
Dies kann vollständig mit Generatorausdrücken inline unter Verwendung von itertools durchgeführt werden, aber es sieht ziemlich seltsam aus:
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 )
Hier sind meine Timings:
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