Я хочу перебрать каждую строку всего файла. Один из способов сделать это - прочитать весь файл, сохранить его в списке, а затем перейти по интересующей линии. Этот метод использует много памяти, поэтому я ищу альтернативу.
Мой код до сих пор:
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
.
Какие-либо предложения?
Цель состоит в том, чтобы вычислить парное сходство строк, то есть для каждой строки в файле, я хочу вычислить расстояние Левенштейна для каждой другой строки.
Ответы:
Правильный, полностью Pythonic способ чтения файла заключается в следующем:
В
with
заявлении ручки открытия и закрытия файла, в том числе , если возбуждается исключение во внутреннем блоке. Онfor line in f
рассматривает файловый объектf
как итеративный, который автоматически использует буферизованный ввод-вывод и управление памятью, поэтому вам не нужно беспокоиться о больших файлах.источник
for line in f:
работает? Я имею в виду, как возможна перебор файлового объекта?__iter__
, который сообщает ему, что делать. Файловые объекты определяют этот специальный метод для возврата итератора по строкам. (Примерно.)Два эффективных по памяти способа в ранжированном порядке (первый - лучший) -
with
- поддерживается с Python 2.5 и вышеyield
если вы действительно хотите контролировать, сколько читать1. использование
with
with
хороший и эффективный способ чтения больших файлов. Преимущества - 1) файловый объект автоматически закрывается после выхода изwith
блока исполнения. 2) обработка исключений внутриwith
блока. 3)for
цикл памяти перебираетf
файловый объект построчно. внутренне он выполняет буферизованный ввод-вывод (для оптимизации дорогостоящих операций ввода-вывода) и управление памятью.2. использование
yield
Иногда может потребоваться более детальный контроль над тем, сколько читать в каждой итерации. В этом случае используйте iter & yield . Обратите внимание, что при использовании этого метода необходимо закрыть файл в конце.
Подводные камни и для полноты - ниже методы не так хороши или не так элегантны для чтения больших файлов, но, пожалуйста, прочитайте, чтобы получить всестороннее понимание.
В Python наиболее распространенный способ чтения строк из файла заключается в следующем:
Когда это сделано,
readlines()
функция (то же самое относится и кread()
функции) загружает весь файл в память, а затем перебирает его. Немного лучший подход (первые два упомянутых метода являются лучшими) для больших файлов заключается в использованииfileinput
модуля следующим образом:fileinput.input()
вызов читает строку последовательно, но не сохраняет их в памяти после того, как они были считаны или даже просто так это, так какfile
в питоной итерации.Ссылки
источник
for line in open(...).readlines(): <do stuff>
. Почему ты?! Вы только что потеряли все преимущества умного буферизированного ввода-вывода Python без какой-либо выгоды.readlines
и объяснив, почему это нехорошо (потому что он читает файл в память), затем объяснив, чтоfileinput
делает модуль и почему вы Возможно, вы захотите использовать его поверх других методов, затем объясните, как разбиение файла на блоки улучшает работу ввода-вывода, и приведите пример функции разбиения на блоки (но упомяните, что Python уже делает это для вас, так что вам это не нужно). Но просто дать пять способов решить простую проблему, четыре из которых в данном случае неверны, нехорошо.Для удаления новых строк:
С универсальной поддержкой новой строки все строки файла текст будет казаться завершаться
'\n'
, независимо терминаторы в файле,'\r'
,'\n'
или'\r\n'
.РЕДАКТИРОВАТЬ - Чтобы указать универсальную поддержку новой строки:
open(file_path, mode='rU')
- требуется [спасибо @Dave ]open(file_path, mode='rU')
- необязательноopen(file_path, newline=None)
- необязательноnewline
Параметр поддерживается только в Python 3 и по умолчаниюNone
. Вmode
параметрах по умолчанию'r'
во всех случаях.U
Осуждается в Python 3. В Python 2 на Windows , другой механизм , как представляется , перевести\r\n
в\n
.Docs:
Для сохранения собственных терминаторов строки:
Двоичный режим все еще может анализировать файл на строки с
in
. Каждая строка будет иметь те терминаторы, которые есть в файле.Благодаря @katrielalex «s ответ , Python, открытый () документ, и IPython эксперименты.
источник
open(file_path, 'rU')
включить универсальные переводы строк.это возможный способ чтения файла в Python:
он не выделяет полный список. Он перебирает строки.
источник
with open(input_file) as f:
. Это спасет васf.close()
и гарантирует, что вы случайно не забудете закрыть его. Предотвращает утечки памяти и все, что очень важно при чтении файлов.Немного контекста заранее о том, откуда я иду. Фрагменты кода в конце.
Когда я могу, я предпочитаю использовать инструмент с открытым исходным кодом, такой как H2O, для высокопроизводительного параллельного чтения файлов CSV, но этот инструмент ограничен в наборе функций. Я заканчиваю тем, что пишу много кода для создания конвейеров данных, прежде чем подавать его в кластер H2O для обучения под наблюдением.
Я читал файлы, такие как набор данных HIGGS 8 ГБ из репозитория UCI и даже файлы CSV 40 ГБ для целей обработки данных, значительно быстрее, добавляя много параллелизма с помощью объекта пула и карты функции многопроцессорной библиотеки. Например, кластеризация с поиском ближайшего соседа, а также алгоритмами кластеризации DBSCAN и Маркова требует некоторого изощренного параллельного программирования, чтобы обойти некоторые серьезные проблемы с памятью и временем настенных часов.
Я обычно люблю разбивать файл по строкам на части, используя инструменты gnu, а затем glob-filemask их все, чтобы найти и прочитать их параллельно в программе python. Я обычно использую что-то вроде 1000+ частичных файлов. Выполнение этих приемов очень помогает в скорости обработки и ограничении памяти.
Pandas dataframe.read_csv является однопоточным, поэтому вы можете сделать эти трюки, чтобы сделать панды более быстрыми, запустив map () для параллельного выполнения. Вы можете использовать htop, чтобы увидеть, что с обычными старыми последовательными пандами dataframe.read_csv 100% ЦП только на одном ядре - это фактическое узкое место в pd.read_csv, а не на диске вообще.
Я должен добавить, что я использую SSD на быстрой шине видеокарты, а не вращающийся HD на шине SATA6, плюс 16 процессорных ядер.
Кроме того, другой метод, который я обнаружил, прекрасно работает в некоторых приложениях - это параллельное чтение файла CSV в одном гигантском файле, начиная с каждого рабочего с разным смещением в файле, вместо предварительного разделения одного большого файла на множество файлов деталей. Используйте Python для поиска файлов () и Tell () в каждом параллельном работнике, чтобы читать большой текстовый файл в виде полос, с разными байтовыми смещениями начальных и конечных байтов в большом файле, одновременно в одно и то же время. Вы можете выполнить поиск по всем регулярным выражениям в байтах и вернуть счетчик перевода строки. Это частичная сумма. Наконец, суммируйте частичные суммы, чтобы получить глобальную сумму, когда функция карты возвращается после того, как рабочие закончили.
Ниже приведены некоторые примеры тестов с использованием трюка с параллельным байтовым смещением:
Я использую 2 файла: HIGGS.csv составляет 8 ГБ. Это из хранилища машинного обучения UCI. all_bin .csv имеет размер 40,4 ГБ и является результатом моего текущего проекта. Я использую 2 программы: GNU wc, которая поставляется вместе с Linux, и программу на python fastread.py, которую я разработал.
Это примерно 4,5 ГБ / с, или 45 ГБ / с, скорость записи файла. Это не вращающийся жесткий диск, мой друг. Это на самом деле Samsung Pro 950 SSD.
Ниже приведен тест скорости для того же файла, который был посчитан строкой gnu wc, скомпилированной программой на чистом C.
Круто то, что вы можете видеть, что моя программа на чистом Python в этом случае практически соответствовала скорости скомпилированной программы gnu wc. Python интерпретируется, но C компилируется, так что это довольно интересный подвиг скорости, я думаю, вы согласитесь. Конечно, wc действительно нужно заменить на параллельную программу, и тогда он действительно побьет все мои программы на python. Но в нынешнем виде gnu wc - это просто последовательная программа. Вы делаете то, что можете, и Python может делать параллельное сегодня. Компиляция Cython может помочь мне (в другое время). Также отображенные в память файлы еще не исследовались.
Вывод: скорость хороша для чистой программы на Python по сравнению с программой на Си. Тем не менее, недостаточно использовать чистую программу на Python поверх программы на C, по крайней мере, для целей линейного монтажа. Обычно этот метод может использоваться для обработки других файлов, поэтому этот код на Python все еще хорош.
Вопрос: Будет ли компиляция регулярного выражения только один раз и передача его всем работникам улучшать скорость? Ответ: Предварительная компиляция Regex НЕ помогает в этом приложении. Я предполагаю, что причина в том, что накладные расходы на сериализацию и создание процессов для всех работников являются доминирующими.
Еще кое-что. Параллельное чтение файла CSV даже помогает? Является ли диск узким местом или процессором? Многие так называемые ответы с самым высоким рейтингом в stackoverflow содержат общую мудрость разработчиков, согласно которой вам нужен только один поток для чтения файла, говорят они, лучше всего. Хотя они уверены?
Давайте выясним:
Ах да, да, это так. Параллельное чтение файлов работает довольно хорошо. Ну вот и все!
Ps. В случае, если некоторые из вас хотят знать, что если balanceFactor равнялся 2 при использовании одного рабочего процесса? Ну это ужасно
Ключевые части программы python fastread.py:
Определение для PartitionDataToWorkers - это просто обычный последовательный код. Я пропустил это на тот случай, если кто-то еще захочет немного попрактиковаться в том, что такое параллельное программирование. Я бесплатно раздал более сложные части: проверенный и работающий параллельный код, для вашего удобства обучения.
Спасибо: Проект H2O с открытым исходным кодом, разработанный Арно и Клиффом и сотрудниками H2O за их великолепное программное обеспечение и обучающие видео, которые вдохновили меня на этот высокопроизводительный параллельный считыватель байтовых смещений на python, как показано выше. H2O выполняет параллельное чтение файлов с использованием Java, может вызываться программами на Python и R и быстро сходит с ума, быстрее, чем что-либо на планете, при чтении больших файлов CSV.
источник
Katrielalex предоставил способ открыть и прочитать один файл.
Однако, как работает ваш алгоритм, он читает весь файл для каждой строки файла. Это означает, что общий объем чтения файла и вычисления расстояния Левенштейна будет выполнен N * N, если N - количество строк в файле. Поскольку вас беспокоит размер файла, и вы не хотите хранить его в памяти, меня беспокоит результирующее квадратичное время выполнения . Ваш алгоритм относится к классу алгоритмов O (n ^ 2), которые часто можно улучшить с помощью специализации.
Я подозреваю, что вы уже знаете соотношение между памятью и временем выполнения здесь, но, возможно, вы захотите выяснить, существует ли эффективный способ вычисления нескольких расстояний Левенштейна параллельно. Если так, то было бы интересно поделиться своим решением здесь.
Сколько строк в ваших файлах и на каком компьютере (мощность mem & cpu) должен работать ваш алгоритм, и каково допустимое время выполнения?
Код будет выглядеть так:
Но вопрос в том, как вы сохраняете расстояния (матрицу?) И можете ли вы получить преимущество от подготовки, например, external_line для обработки, или кэширования некоторых промежуточных результатов для повторного использования.
источник
Если вы хотите, например, проверить определенную строку на длину более 10, работайте с тем, что у вас уже есть.
источник
Из документации на python для fileinput .input ():
далее, определение функции:
читая между строк, это говорит мне, что это
files
может быть список, чтобы вы могли иметь что-то вроде:Смотрите здесь для получения дополнительной информации
источник
Я настоятельно рекомендую не использовать загрузку файлов по умолчанию, так как это ужасно медленно. Вы должны посмотреть на numpy функции и функции IOpro (например, numpy.loadtxt ()).
http://docs.scipy.org/doc/numpy/user/basics.io.genfromtxt.html
https://store.continuum.io/cshop/iopro/
Затем вы можете разбить вашу попарную операцию на куски:
Почти всегда гораздо быстрее загружать данные порциями, а затем выполнять над ними матричные операции, чем делать их поэлементно !!
источник
Нужно часто читать большой файл из последней позиции чтения?
Я создал скрипт, используемый для резки файла Apache access.log несколько раз в день. Поэтому мне нужно было установить курсор на последнюю строку, проанализированную во время последнего выполнения . Для этого я использовал
file.seek()
иfile.seek()
методы, позволяющие хранить курсор в файле.Мой код:
источник
Лучший способ прочитать большой файл, строка за строкой - использовать функцию перечисления Python
источник