Мне нужно получить количество строк большого файла (сотни тысяч строк) в Python. Как наиболее эффективно использовать память и время?
На данный момент я делаю:
def file_len(fname):
with open(fname) as f:
for i, l in enumerate(f):
pass
return i + 1
Можно ли сделать что-то лучше?
python
text-files
line-count
SilentGhost
источник
источник
enumerate(f, 1)
а угробитьi + 1
?Ответы:
Вы не можете стать лучше, чем это.
В конце концов, любое решение должно будет прочитать весь файл, выяснить, сколько у
\n
вас есть, и вернуть этот результат.У вас есть лучший способ сделать это, не читая весь файл? Не уверен ... Лучшее решение всегда будет связано с вводом / выводом, лучшее, что вы можете сделать, - это убедиться, что вы не используете ненужную память, но похоже, что вы это покрыли.
источник
Одна строка, вероятно, довольно быстро:
источник
Я считаю, что файл с отображением в памяти будет самым быстрым решением. Я попробовал четыре функции: функция, опубликованная OP (
opcount
); простая итерация по строкам в файле (simplecount
); readline с полем с отображением в память (mmap) (mapcount
); и решение для чтения из буфера, предложенное Николаем Харечко (bufcount
).Я запускал каждую функцию пять раз и вычислял среднее время выполнения для текстового файла длиной в 1,2 миллиона строк.
Windows XP, Python 2.5, 2 ГБ оперативной памяти, процессор AMD 2 ГГц
Вот мои результаты:
Редактировать : номера для Python 2.6:
Таким образом, стратегия чтения из буфера кажется самой быстрой для Windows / Python 2.6
Вот код:
источник
wccount()
это самый быстрый gist.github.com/0ac760859e614cd03652Мне приходилось публиковать это на похожем вопросе, пока оценка моей репутации немного не подскочила (спасибо тому, кто ударил меня!).
Все эти решения игнорируют один способ сделать это значительно быстрее, а именно, используя небуферизованный (необработанный) интерфейс, используя байтовые массивы и выполняя собственную буферизацию. (Это применимо только в Python 3. В Python 2 необработанный интерфейс может или не может использоваться по умолчанию, но в Python 3 вы по умолчанию будете использовать Unicode.)
Используя модифицированную версию инструмента синхронизации, я считаю, что следующий код работает быстрее (и немного более питонно), чем любое из предложенных решений:
Используя отдельную функцию генератора, она быстрее запускается:
Это можно сделать полностью с помощью встроенных выражений генераторов, используя itertools, но это выглядит довольно странно:
Вот мои сроки:
источник
wccount
в этой таблице дляwc
инструмента оболочки подпроцесса ?rawincount
решение менее странным, используяbufgen = iter(partial(f.raw.read, 1024*1024), b'')
вместо комбинированияtakewhile
иrepeat
.Вы можете выполнить подпроцесс и запустить
wc -l filename
источник
Вот программа на Python, которая использует многопроцессорную библиотеку для распределения подсчета строк по машинам / ядрам. Мой тест улучшает подсчет 20-миллионного файла строки с 26 до 7 секунд, используя 8-ядерный сервер Windows 64. Примечание: не используя отображение памяти делает вещи намного медленнее.
источник
Однострочное решение bash, аналогичное этому ответу , с использованием современной
subprocess.check_output
функции:источник
wc -l
занимает ~ 5 секунд.shell=True
это плохо для безопасности, лучше избегать этого.Я бы использовал метод файлового объекта Python
readlines
следующим образом:Это откроет файл, создаст список строк в файле, посчитает длину списка, сохранит ее в переменной и снова закроет файл.
источник
xreadlines
устарел с 2.3, так как он просто возвращает итератор.for line in file
это заявленная замена. См. Docs.python.org/2/library/stdtypes.html#file.xreadlinesисточник
Вот то, что я использую, кажется довольно чистым:
ОБНОВЛЕНИЕ: Это немного быстрее, чем использование чистого Python, но за счет использования памяти. Подпроцесс запустит новый процесс с тем же объемом памяти, что и родительский процесс, пока он выполняет вашу команду.
источник
:-)
Это самая быстрая вещь, которую я нашел, используя чистый питон. Вы можете использовать любой объем памяти, который вы хотите, установив буфер, хотя 2 ** 16 кажется приятным местом на моем компьютере.
Я нашел ответ здесь Почему чтение строк из stdin в C ++ намного медленнее, чем в Python? и чуть-чуть подправил. Это очень хорошее чтение, чтобы понять, как быстро считать строки, хотя
wc -l
все еще примерно на 75% быстрее, чем что-либо еще.источник
Я получил небольшое (4-8%) улучшение в этой версии, в которой повторно используется постоянный буфер, поэтому следует избегать использования памяти или GC:
Вы можете поиграть с размером буфера и, возможно, увидеть небольшое улучшение.
источник
Ответ Кайла
вероятно, лучшая альтернатива для этого
Вот сравнение производительности обоих
источник
Одноканальное решение:
Мой фрагмент:
источник
os.system()
в переменную и обработать их так или иначе.Просто для завершения вышеуказанных методов я попробовал вариант с модулем fileinput:
И передал файл 60-миллиметровых строк всем вышеупомянутым методам:
Для меня немного удивительно, что fileinput настолько плох и масштабируется гораздо хуже, чем все остальные методы ...
источник
Для меня этот вариант будет самым быстрым:
причины: буферизация быстрее, чем чтение построчно, а
string.count
также очень быстроисточник
Этот код короче и понятнее. Это, наверное, лучший способ:
источник
Я изменил регистр буфера следующим образом:
Теперь также учитываются пустые файлы и последняя строка (без \ n).
источник
Что насчет этого
источник
count = max(enumerate(open(filename)))[0]
источник
enumerate()
- это начальное количество в соответствии с docs.python.org/2/library/functions.html#enumerateисточник
источник
Если кто-то хочет получить дешевый счетчик строк в Python в Linux, я рекомендую этот метод:
file_path может быть как абстрактный путь к файлу или относительный путь. Надеюсь, что это может помочь.
источник
Как насчет этого?
источник
Как насчет этой строки?
Использование этого метода занимает 0,003 с, чтобы синхронизировать его с файлом из 3900 строк.
источник
источник
Простой метод:
1)
2)
3)
источник
Результатом открытия файла является итератор, который можно преобразовать в последовательность, имеющую длину:
это более кратко, чем ваш явный цикл, и позволяет избежать
enumerate
.источник
Вы можете использовать
os.path
модуль следующим образом:где
Filename
абсолютный путь к файлу.источник
os.path
?Если файл может поместиться в памяти, то
источник