Как читать большой файл построчно?

Я хочу перебрать каждую строку всего файла. Один из способов сделать это - прочитать весь файл, сохранить его в списке, а затем перейти по интересующей строке. Этот метод использует много памяти, поэтому я ищу альтернативу.

Мой код на данный момент:

for each_line in fileinput.input(input_file):
    do_something(each_line)

    for each_line_again in fileinput.input(input_file):
        do_something(each_line_again)

Выполнение этого кода дает сообщение об ошибке: device active.

Какие-либо предложения?

Цель состоит в том, чтобы вычислить попарное сходство строк, то есть для каждой строки в файле я хочу рассчитать расстояние Левенштейна с каждой другой строкой.


person 384X21    schedule 04.11.2011    source источник
comment
Зачем нужно заново читать весь файл для каждой строки? Может быть, если вы расскажете, чего пытаетесь достичь, кто-то сможет предложить лучший подход.   -  person JJJ    schedule 04.11.2011


Ответы (11)


Правильный, полностью питонический способ чтения файла следующий:

with open(...) as f:
    for line in f:
        # Do something with 'line'

Оператор with обрабатывает открытие и закрытие файла, в том числе в случае возникновения исключения во внутреннем блоке. for line in f рассматривает файловый объект f как итерацию, которая автоматически использует буферизованный ввод-вывод и управление памятью, поэтому вам не нужно беспокоиться о больших файлах.

Должен быть один - и желательно только один - очевидный способ сделать это.

person Katriel    schedule 04.11.2011
comment
да, это лучшая версия с python 2.6 и выше - person Simon Bergot; 04.11.2011
comment
Я лично предпочитаю генераторы и сопрограммы для работы с конвейерами данных. - person jldupont; 04.11.2011
comment
Какая будет лучшая стратегия, если файл представляет собой огромный текстовый файл, но с одной строкой, а идея состоит в том, чтобы обрабатывать слова? - person mfcabrera; 18.12.2013
comment
@mfcabrera вам придется иметь дело с блоками самостоятельно, в этом случае: Python буферизует только строки. Смотрите другие ответы. - person Katriel; 20.12.2013
comment
@mfcabrera какие-либо ссылки на примеры для разбора огромных однострочных текстовых файлов, что это значит, иметь дело с блоками? - person Jorge Vidinha; 07.05.2014
comment
@JorgeVidinha Вот как я это делаю: gist.github.com/mfcabrera/14015179cdfd2dd2a2fa - person mfcabrera; 07.05.2014
comment
Может кто-нибудь объяснить, как for line in f: работает? Я имею в виду, как возможен перебор файлового объекта? - person haccks; 09.02.2015
comment
Если вы перебираете объект, Python ищет в списке методов объекта специальный метод с именем __iter__, который сообщает ему, что делать. Файловые объекты определяют этот специальный метод для возврата итератора по строкам. (Грубо.) - person Katriel; 10.02.2015
comment
Просто вопрос по этому поводу - возвращает ли приведенный выше код строку в виде строки? Я мог бы сделать что-нибудь вроде: myString = line; (сделать что-нибудь с myString)? - person David Tamrazov; 13.11.2015
comment
У меня быстрый вопрос по циклу for: автоматически ли он оптимизирует чтение фрагментов данных, а не одного за другим? чтобы он не переходил к внешнему файлу слишком часто? - person Sardonic; 24.01.2016
comment
Хорошо, если бы у кого-то был такой же вопрос, как и у меня. Оптимизацией занимается не цикл for, а основная единица чтения файла - страница, которая зависит от архитектуры. Таким образом, даже если я сделаю один вызов readline (), он прочитает более одной строки, но прочитает часть (или страницу) диска в ОЗУ. - person Sardonic; 04.02.2016
comment
Когда вы пытаетесь разделить его, чтобы получить часть, требуется только первое разделение. Какие-либо предложения?? - person Antonio López Ruiz; 24.07.2016
comment
почему не просто f = open() - person TheCrazyProfessor; 01.06.2017
comment
Есть ли способ узнать, когда я нахожусь на последней строчке в этом решении? - person akn; 21.10.2017
comment
Нет, вы не узнаете, находитесь ли вы на последней строке, пока не попытаетесь прочитать строку, а ее нет (кто-то может даже записать новую строку в файл, пока вы все еще читаете его). Вы можете добавить else в цикл, чтобы что-то сделать после последней строки! - person Katriel; 25.10.2017
comment
В Python 2.7 при открытии файла с символами новой строки, заканчивающимися на \r, мне пришлось open('file.txt','rU') включить универсальная поддержка новой строки. - person Dave; 05.12.2017
comment
Это только мне кажется, или этот ответ больше не полезен, учитывая правку в исходном вопросе? Запуск цикла with для каждой строки в файле означает открытие и просмотр (большого) файла для каждой строки в этом файле. Это безнадежно неэффективно. - person Melvin; 09.01.2018
comment
@ Мелвин Я не думаю, это то, что подсказывает ответ. Когда я его прочитал, окончательный код выглядел бы так with open(args*) as f:\n for line in f:\n for line in f:\n do_stuff(). Я не могу отформатировать это в комментарии, но вы поняли идею. - person hajef; 24.06.2019

Два эффективных способа использования памяти в ранжированном порядке (первый лучше) -

  1. использование with - поддерживается начиная с Python 2.5 и выше
  2. используйте yield, если вы действительно хотите контролировать, сколько читать

1. использование with

with - красивый и эффективный питонический способ чтения больших файлов. преимущества - 1) файловый объект автоматически закрывается после выхода из with блока выполнения. 2) обработка исключений внутри блока with. 3) цикл памяти for выполняет итерацию f файлового объекта построчно. внутри он выполняет буферизованный ввод-вывод (для оптимизации дорогостоящих операций ввода-вывода) и управление памятью.

with open("x.txt") as f:
    for line in f:
        do something with data

2. использование yield

Иногда может потребоваться более детальный контроль над тем, сколько читать на каждой итерации. В этом случае используйте iter & yield. Обратите внимание, что с помощью этого метода нужно явно закрыть файл в конце.

def readInChunks(fileObj, chunkSize=2048):
    """
    Lazy function to read a file piece by piece.
    Default chunk size: 2kB.

    """
    while True:
        data = fileObj.read(chunkSize)
        if not data:
            break
        yield data

f = open('bigFile')
for chunk in readInChunks(f):
    do_something(chunk)
f.close()

Подводные камни и для полноты картины - приведенные ниже методы не так хороши или не так элегантны для чтения больших файлов, но, пожалуйста, прочтите, чтобы получить полное представление.

В Python наиболее распространенным способом чтения строк из файла является выполнение следующих действий:

for line in open('myfile','r').readlines():
    do_something(line)

Однако, когда это будет сделано, функция readlines() (то же самое относится и к функции read()) загружает весь файл в память, а затем выполняет итерацию по нему. Несколько лучший подход (первые два упомянутых выше метода являются лучшими) для больших файлов - использовать модуль fileinput, как показано ниже:

import fileinput

for line in fileinput.input(['myfile']):
    do_something(line)

вызов fileinput.input() читает строки последовательно, но не сохраняет их в памяти после того, как они были прочитаны, или даже просто так, поскольку file в python повторяется.

использованная литература

  1. Python с оператором
person Srikar Appalaraju    schedule 04.11.2011
comment
-1 Это вообще плохая идея делать for line in open(...).readlines(): <do stuff>. Почему ты?! Вы только что потеряли все преимущества умного буферизованного ввода-вывода итератора Python без всякой пользы. - person Katriel; 04.11.2011
comment
@Srikar: есть время и место для того, чтобы дать все возможные решения проблемы; обучение новичка тому, как вводить файлы, - это не так. Захоронить правильный ответ в конце длинного поста, полного неправильных ответов, - не очень хорошее обучение. - person Katriel; 04.11.2011
comment
@Srikar: Вы могли бы значительно улучшить свой пост, поместив правильный путь вверху, затем упомянув readlines и объяснив, почему это нехорошо (потому что он считывает файл в память), затем объяснив, что делает модуль fileinput и почему вы можете захотеть использовать его вместо других методов, а затем объясните, как фрагментирование файла улучшает ввод-вывод, и приведите пример функции фрагментации (но упомянув, что Python уже делает это за вас, поэтому вам не нужно). Но просто дать пять способов решения простой проблемы, четыре из которых в данном случае неверны, нехорошо. - person Katriel; 04.11.2011
comment
Все, что вы добавляете для полноты картины, добавляйте в последнюю очередь, а не в первую очередь. Сначала покажите правильный путь. - person m000; 21.09.2013
comment
@katrielalex пересмотрел мой ответ и обнаружил, что он требует реструктуризации. Я понимаю, как более ранний ответ может вызвать путаницу. Надеюсь, это прояснит это для будущих пользователей. - person Srikar Appalaraju; 21.09.2013
comment
Может быть, решение 1 + 2? Я имею в виду заключить оператор with в функцию генератора, а затем выдать строки. - person Davide Brunato; 24.07.2017
comment
Для опытных пользователей обратите внимание, что для новичка просмотр списка подводных камней может быть чрезвычайно полезным, особенно при просмотре кода других людей и столкновении с теми же ошибками. Для новичков это было полезно, как и pandas.pydata .org / pandas-docs / version / 0.19 / gotchas.html. - person LabGecko; 27.05.2019

Чтобы удалить символы новой строки:

with open(file_path, 'rU') as f:
    for line_terminated in f:
        line = line_terminated.rstrip('\n')
        ...

С универсальной поддержкой новой строки все строки текстового файла будут завершаться с помощью '\n' независимо от терминаторов в файле: '\r', '\n' или '\r\n'.

ИЗМЕНИТЬ - Чтобы указать универсальную поддержку новой строки:

  • Python 2 в Unix - open(file_path, mode='rU') - требуется [спасибо, @Dave]
  • Python 2 в Windows - open(file_path, mode='rU') - необязательно
  • Python 3 - open(file_path, newline=None) - необязательно

Параметр newline поддерживается только в Python 3 и по умолчанию равен None. Параметр mode по умолчанию равен 'r' во всех случаях. U не рекомендуется в Python 3. В Python 2 в Windows, похоже, есть другой механизм для перевода \r\n в \n.

Документы:

Чтобы сохранить собственные терминаторы строк:

with open(file_path, 'rb') as f:
    with line_native_terminated in f:
        ...

В двоичном режиме файл все еще может быть разбит на строки с in. Каждая строка будет иметь терминаторы, которые есть в файле.

Благодаря @katrielalex 673991 "> answer, документ Python open (), и эксперименты iPython.

person Bob Stein    schedule 15.09.2015
comment
В Python 2.7 мне пришлось open(file_path, 'rU') включить универсальные символы новой строки. - person Dave; 05.12.2017

это возможный способ чтения файла в python:

f = open(input_file)
for line in f:
    do_stuff(line)
f.close()

он не размещает полный список. Он перебирает строки.

person Simon Bergot    schedule 04.11.2011
comment
Хотя это работает, это определенно не канонический способ. Канонический способ - использовать оболочку контекста, например with open(input_file) as f:. Это сэкономит вам f.close() и гарантирует, что вы случайно не забудете его закрыть. Предотвращает утечки памяти и все такое, что немаловажно при чтении файлов. - person Mast; 28.12.2016
comment
Как сказал @Mast, это не канонический способ, поэтому проголосуйте против. - person azuax; 03.01.2017

Некоторый контекст впереди того, откуда я. Фрагменты кода в конце.

По возможности я предпочитаю использовать инструмент с открытым исходным кодом, такой как H2O, для сверхвысокопроизводительного параллельного чтения файлов CSV, но этот инструмент имеет ограниченный набор функций. Я заканчиваю тем, что пишу много кода для создания конвейеров обработки данных, прежде чем передавать их в кластер H2O для собственно контролируемого обучения.

Я читал такие файлы, как набор данных HIGGS объемом 8 ГБ из репозитория UCI и даже файлы CSV размером 40 ГБ для целей науки о данных, значительно быстрее, добавляя много параллелизма с помощью объекта пула библиотеки многопроцессорной обработки и функции карты. Например, кластеризация с поиском ближайшего соседа, а также алгоритмы кластеризации DBSCAN и Маркова требуют некоторой тонкости параллельного программирования, чтобы обойти некоторые серьезные проблемы с памятью и временем настенных часов.

Обычно мне нравится разбивать файл по строкам на части, используя сначала инструменты gnu, а затем glob-filemask их все, чтобы найти и прочитать их параллельно в программе python. Обычно я использую около 1000+ частичных файлов. Выполнение этих трюков очень помогает с ограничениями скорости обработки и памяти.

Pandas dataframe.read_csv является однопоточным, поэтому вы можете использовать эти трюки, чтобы сделать pandas намного быстрее, запустив map () для параллельного выполнения. Вы можете использовать htop, чтобы увидеть, что с простыми старыми последовательными pandas dataframe.read_csv 100% ЦП только на одном ядре является фактическим узким местом в pd.read_csv, а не диском вообще.

Я должен добавить, что использую SSD на шине быстрой видеокарты, а не вращающийся HD на шине SATA6, плюс 16 ядер процессора.

Кроме того, я обнаружил, что еще один метод, который отлично работает в некоторых приложениях, - это параллельное чтение CSV-файла в одном гигантском файле, запуск каждого рабочего с разным смещением в файл, а не предварительное разбиение одного большого файла на несколько файлов частей. Используйте python file seek () и tell () в каждом параллельном работнике, чтобы читать большой текстовый файл полосами, в разных местах начального и конечного байта смещения байта в большом файле, все одновременно и одновременно. Вы можете выполнить регулярное выражение findall для байтов и вернуть количество переводов строки. Это частичная сумма. Наконец, просуммируйте частичные суммы, чтобы получить глобальную сумму, когда функция карты вернется после того, как рабочие закончили.

Ниже приведены несколько примеров тестов, использующих трюк с параллельным смещением байтов:

Использую 2 файла: HIGGS.csv - 8 Гб. Это из репозитория машинного обучения UCI. all_bin .csv составляет 40,4 ГБ и принадлежит моему текущему проекту. Я использую две программы: программу GNU wc, которая поставляется с Linux, и программу на чистом python fastread.py, которую я разработал.

HP-Z820:/mnt/fastssd/fast_file_reader$ ls -l /mnt/fastssd/nzv/HIGGS.csv
-rw-rw-r-- 1 8035497980 Jan 24 16:00 /mnt/fastssd/nzv/HIGGS.csv

HP-Z820:/mnt/fastssd$ ls -l all_bin.csv
-rw-rw-r-- 1 40412077758 Feb  2 09:00 all_bin.csv

ga@ga-HP-Z820:/mnt/fastssd$ time python fastread.py --fileName="all_bin.csv" --numProcesses=32 --balanceFactor=2
2367496

real    0m8.920s
user    1m30.056s
sys 2m38.744s

In [1]: 40412077758. / 8.92
Out[1]: 4530501990.807175

Это примерно 4,5 ГБ / с, или 45 ГБ / с, при раздаче файлов. Это не вращающийся жесткий диск, мой друг. На самом деле это SSD Samsung Pro 950.

Ниже приведен тест скорости для того же файла, который подсчитывается с помощью gnu wc, программы, скомпилированной на чистом языке C.

Что круто, так это то, что вы можете видеть, что моя программа на чистом python в этом случае практически соответствовала скорости скомпилированной программы C, скомпилированной gnu wc. Python интерпретируется, но C скомпилирован, так что это довольно интересный подвиг скорости, я думаю, вы согласитесь. Конечно, wc действительно нужно преобразовать в параллельную программу, и тогда она действительно выбьет из моей программы на Python носки. Но в нынешнем виде gnu wc - это просто последовательная программа. Вы делаете то, что можете, и python сегодня может делать параллели. Компиляция Cython может мне помочь (в другой раз). Также еще не были исследованы файлы с отображением памяти.

HP-Z820:/mnt/fastssd$ time wc -l all_bin.csv
2367496 all_bin.csv

real    0m8.807s
user    0m1.168s
sys 0m7.636s


HP-Z820:/mnt/fastssd/fast_file_reader$ time python fastread.py --fileName="HIGGS.csv" --numProcesses=16 --balanceFactor=2
11000000

real    0m2.257s
user    0m12.088s
sys 0m20.512s

HP-Z820:/mnt/fastssd/fast_file_reader$ time wc -l HIGGS.csv
11000000 HIGGS.csv

real    0m1.820s
user    0m0.364s
sys 0m1.456s

Вывод: скорость работы программы на чистом Python выше, чем у программы C. Однако этого недостаточно, чтобы использовать чистую программу Python поверх программы C, по крайней мере, для целей подсчета строк. Как правило, этот метод можно использовать для другой обработки файлов, поэтому этот код на Python все еще хорош.

Вопрос: Увеличивает ли скорость однократная компиляция регулярного выражения и его передача всем рабочим? Ответ: Предварительная компиляция Regex НЕ помогает в этом приложении. Я полагаю, причина в том, что накладные расходы на сериализацию и создание процессов для всех рабочих являются доминирующими.

Еще кое-что. Помогает ли параллельное чтение файла CSV? Узким местом является диск или процессор? Многие так называемые популярные ответы на stackoverflow содержат распространенную мудрость разработчиков, согласно которой вам нужен только один поток для чтения файла - лучшее, что вы можете сделать, говорят они. Но уверены ли они?

Давайте разберемся:

HP-Z820:/mnt/fastssd/fast_file_reader$ time python fastread.py --fileName="HIGGS.csv" --numProcesses=16 --balanceFactor=2
11000000

real    0m2.256s
user    0m10.696s
sys 0m19.952s

HP-Z820:/mnt/fastssd/fast_file_reader$ time python fastread.py --fileName="HIGGS.csv" --numProcesses=1 --balanceFactor=1
11000000

real    0m17.380s
user    0m11.124s
sys 0m6.272s

О да, да, это так. Параллельное чтение файлов работает неплохо. Ну вот, поехали!

Пс. В случае, если некоторые из вас хотели знать, что, если бы balanceFactor был равен 2 при использовании одного рабочего процесса? Что ж, это ужасно:

HP-Z820:/mnt/fastssd/fast_file_reader$ time python fastread.py --fileName="HIGGS.csv" --numProcesses=1 --balanceFactor=2
11000000

real    1m37.077s
user    0m12.432s
sys 1m24.700s

Ключевые части программы python fastread.py:

fileBytes = stat(fileName).st_size  # Read quickly from OS how many bytes are in a text file
startByte, endByte = PartitionDataToWorkers(workers=numProcesses, items=fileBytes, balanceFactor=balanceFactor)
p = Pool(numProcesses)
partialSum = p.starmap(ReadFileSegment, zip(startByte, endByte, repeat(fileName))) # startByte is already a list. fileName is made into a same-length list of duplicates values.
globalSum = sum(partialSum)
print(globalSum)


def ReadFileSegment(startByte, endByte, fileName, searchChar='\n'):  # counts number of searchChar appearing in the byte range
    with open(fileName, 'r') as f:
        f.seek(startByte-1)  # seek is initially at byte 0 and then moves forward the specified amount, so seek(5) points at the 6th byte.
        bytes = f.read(endByte - startByte + 1)
        cnt = len(re.findall(searchChar, bytes)) # findall with implicit compiling runs just as fast here as re.compile once + re.finditer many times.
    return cnt

Определение для PartitionDataToWorkers - это просто обычный последовательный код. Я оставил это на случай, если кто-то еще захочет попрактиковаться в параллельном программировании. Я раздал бесплатно самые сложные части: протестированный и работающий параллельный код для вашего обучения.

Спасибо: проекту H2O с открытым исходным кодом, выполненному Арно и Клиффом и сотрудниками H2O за их отличное программное обеспечение и обучающие видеоролики, которые послужили мне вдохновением для этого чистого высокопроизводительного параллельного считывателя байтов смещения на Python, как показано выше. H2O выполняет параллельное чтение файлов с использованием java, вызывается программами на Python и R и работает безумно быстро, быстрее, чем что-либо на планете, при чтении больших файлов CSV.

person Geoffrey Anderson    schedule 02.02.2017
comment
По сути, это и есть параллельные блоки. Кроме того, я ожидаю, что SSD и Flash - единственные устройства хранения, совместимые с этой техникой. Спиннинг HD вряд ли будет совместим. - person Geoffrey Anderson; 02.02.2017
comment
Как вы учли дисковые файлы кеширования ОС? - person JamesThomasMoon; 20.12.2019

Katrielalex предоставил возможность открывать и читать один файл.

Однако, как работает ваш алгоритм, он читает весь файл для каждой строки файла. Это означает, что общий объем чтения файла и вычисление расстояния Левенштейна будет выполняется N * N, если N - количество строк в файле. Поскольку вас беспокоит размер файла и вы не хотите хранить его в памяти, меня беспокоит результат квадратичное время выполнения. Ваш алгоритм относится к классу алгоритмов O (n ^ 2), который часто можно улучшить с помощью специализации.

Я подозреваю, что вы уже знаете здесь компромисс между памятью и временем выполнения, но, возможно, вы захотите выяснить, есть ли эффективный способ параллельного вычисления нескольких расстояний Левенштейна. Если да, то было бы интересно поделиться здесь своим решением.

Сколько строк у ваших файлов, и на какой машине (память и мощность процессора) должен работать ваш алгоритм, и каково допустимое время выполнения?

Код будет выглядеть так:

with f_outer as open(input_file, 'r'):
    for line_outer in f_outer:
        with f_inner as open(input_file, 'r'):
            for line_inner in f_inner:
                compute_distance(line_outer, line_inner)

Но вопрос в том, как вы храните расстояния (матрицу?) И можете ли вы получить преимущество, например, при подготовке. external_line для обработки или кэширования некоторых промежуточных результатов для повторного использования.

person cfi    schedule 04.11.2011
comment
Я хочу сказать, что этот пост не содержит ответа на вопрос, а просто еще несколько вопросов! ИМО, это лучше подходит в качестве комментария. - person Katriel; 16.11.2011
comment
@katriealex: Эээ. Странный. Вы видели вложенные циклы, расширяющие ваш собственный ответ, чтобы он соответствовал актуальному вопросу? Я могу убрать свои вопросы здесь из своего ответа, и еще достаточно контента, чтобы гарантировать, что это будет, хотя и частичным, ответом. Я также мог бы согласиться, если бы вы отредактировали свой собственный ответ, включив в него пример вложенного цикла, который был явно задан вопросом, а затем я с радостью могу удалить свой собственный ответ. Но отрицательный голос - это то, чего я вообще не понимаю. - person cfi; 16.11.2011
comment
Справедливо; Я действительно не вижу демонстрации вложенных циклов for в качестве ответа на вопрос, но я думаю, что он довольно сильно ориентирован на новичков. Голос против удален. - person Katriel; 16.11.2011

#Using a text file for the example
with open("yourFile.txt","r") as f:
    text = f.readlines()
for line in text:
    print line
  • Откройте свой файл для чтения (r)
  • Прочтите файл целиком и сохраните каждую строку в список (текст).
  • Прокрутите список, печатая каждую строку.

Если вы хотите, например, проверить определенную строку на длину более 10, работайте с тем, что у вас уже есть.

for line in text:
    if len(line) > 10:
        print line
person loxsat    schedule 30.07.2016
comment
Не лучший вариант для этого вопроса, но этот код в основном полезен в случае, если то, что вы ищете. Хлюпает (чтение всего файла сразу). Это был мой случай, и Google привел меня сюда. +1. Кроме того, для атомарности, или если вы выполняете длительную обработку в цикле, может закончиться быстрее, чтобы прочитать весь файл - person ntg; 24.11.2016
comment
Также немного улучшен код: 1. После закрытия не требуется: (docs. python.org/2/tutorial/inputoutput.html, выполните поиск по запросу. Рекомендуется использовать ключевое слово with ...) 2. текст может быть обработан после чтения файла (кроме цикла with .... ) - person ntg; 24.11.2016

Из документации python для fileinput .input ():

Выполняется итерация по строкам всех файлов, перечисленных в sys.argv[1:], по умолчанию sys.stdin, если список пуст.

далее определение функции:

fileinput.FileInput([files[, inplace[, backup[, mode[, openhook]]]]])

если читать между строк, это говорит мне, что files может быть списком, так что у вас может быть что-то вроде:

for each_line in fileinput.input([input_file, input_file]):
  do_something(each_line)

Дополнительную информацию см. здесь.

person KevinDTimm    schedule 04.11.2011

Я настоятельно рекомендую не использовать загрузку файлов по умолчанию, так как она ужасно медленная. Вы должны изучить функции numpy и функции IOpro (например, numpy.loadtxt ()).

http://docs.scipy.org/doc/numpy/user/basics.io.genfromtxt.html

https://store.continuum.io/cshop/iopro/

Затем вы можете разбить вашу попарную операцию на куски:

import numpy as np
import math

lines_total = n    
similarity = np.zeros(n,n)
lines_per_chunk = m
n_chunks = math.ceil(float(n)/m)
for i in xrange(n_chunks):
    for j in xrange(n_chunks):
        chunk_i = (function of your choice to read lines i*lines_per_chunk to (i+1)*lines_per_chunk)
        chunk_j = (function of your choice to read lines j*lines_per_chunk to (j+1)*lines_per_chunk)
        similarity[i*lines_per_chunk:(i+1)*lines_per_chunk,
                   j*lines_per_chunk:(j+1)*lines_per_chunk] = fast_operation(chunk_i, chunk_j) 

Почти всегда намного быстрее загружать данные кусками, а затем выполнять над ними матричные операции, чем делать это поэлементно !!

person John Haberstroh    schedule 17.10.2014

Вам нужно часто читать большой файл с последней позиции чтения?

Я создал сценарий, используемый для вырезания файла Apache access.log несколько раз в день. Поэтому мне нужно было установить курсор позиции на последней строке, проанализированной во время последнего выполнения. С этой целью я использовал методы file.seek() и file.seek(), которые позволяют сохранять курсор в файле.

Мой код:

ENCODING = "utf8"
CURRENT_FILE_DIR = os.path.dirname(os.path.abspath(__file__))

# This file is used to store the last cursor position
cursor_position = os.path.join(CURRENT_FILE_DIR, "access_cursor_position.log")

# Log file with new lines
log_file_to_cut = os.path.join(CURRENT_FILE_DIR, "access.log")
cut_file = os.path.join(CURRENT_FILE_DIR, "cut_access", "cut.log")

# Set in from_line 
from_position = 0
try:
    with open(cursor_position, "r", encoding=ENCODING) as f:
        from_position = int(f.read())
except Exception as e:
    pass

# We read log_file_to_cut to put new lines in cut_file
with open(log_file_to_cut, "r", encoding=ENCODING) as f:
    with open(cut_file, "w", encoding=ENCODING) as fw:
        # We set cursor to the last position used (during last run of script)
        f.seek(from_position)
        for line in f:
            fw.write("%s" % (line))

    # We save the last position of cursor for next usage
    with open(cursor_position, "w", encoding=ENCODING) as fw:
        fw.write(str(f.tell()))
person Samuel Dauzon    schedule 07.01.2020

Лучший способ прочитать большой файл построчно - использовать функцию python enumerate.

with open(file_name, "rU") as read_file:
    for i, row in enumerate(read_file, 1):
        #do something
        #i in line of that line
        #row containts all data of that line
person Anurag Misra    schedule 24.08.2017
comment
Почему использование enumerate лучше? Единственное преимущество перед принятым ответом заключается в том, что вы получаете индекс, который OP не нужен, и вы делаете код менее читаемым. - person fuyas; 22.09.2017