Мені довелося розмістити це на подібному питанні, поки мій показник репутації трохи не підскочив (дякую тому, хто мене натрапив!).
Усі ці рішення ігнорують один із способів зробити цей запуск значно швидшим, а саме за допомогою розблокованого (необробленого) інтерфейсу, використання байтарейних масивів та власного буферизації. (Це стосується лише Python 3. У Python 2 необроблений інтерфейс може використовуватися або не використовуватись за замовчуванням, але в Python 3 ти будеш типово встановлений у Unicode.)
Використовуючи модифіковану версію інструменту синхронізації, я вважаю, що наступний код швидший (і дещо пітонічніший), ніж будь-яке із запропонованих рішень:
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
Використовуючи окрему функцію генератора, цей запуск швидше:
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 )
Це можна зробити повністю з вбудованими виразами генераторів, використовуючи itertools, але він виглядає досить дивно:
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 )
Ось мої таймінги:
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