метод "для строки в файловом объекте" для чтения файлов - PullRequest
1 голос
/ 10 декабря 2011

Я пытаюсь найти лучший способ прочитать / обработать строки для очень большого файла.Здесь я просто пытаюсь

for line in f:

Часть моего сценария выглядит следующим образом:

o=gzip.open(file2,'w')
LIST=[]
f=gzip.open(file1,'r'):
for i,line in enumerate(f):
   if i%4!=3:
      LIST.append(line)

   else:
      LIST.append(line)
      b1=[ord(x) for x in line]
      ave1=(sum(b1)-10)/float(len(line)-1)
      if (ave1 < 84):
         del LIST[-4:]
output1=o.writelines(LIST)

Мой file1 составляет около 10 ГБ;и когда я запускаю сценарий, использование памяти продолжает увеличиваться до 15 ГБ без вывода.Это означает, что компьютер все еще пытается сначала прочитать весь файл в память, верно?Это действительно ничем не отличается от использования readlines()

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

Но, очевидно, мне все равно нужно беспокоиться о больших файлах .. Я действительно запутался.thx

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

Ответы [ 5 ]

4 голосов
/ 10 декабря 2011

Причина, по которой память хранится вкл. даже после того, как вы используете enumerator, это потому, что вы используете LIST.append(line). Это в основном накапливает все строки файла в списке. Очевидно, все это сидит в памяти. Вам нужно найти способ не накапливать такие строки. Прочитайте, обработайте и перейдите к следующему.

Еще один способ, которым вы могли бы сделать, это прочитать ваш файл в блоках (фактически чтение 1 строки за раз может соответствовать этому критерию, 1chunk == 1line), то есть прочитать небольшую часть процесса файла, который он прочитал, затем прочитать следующий блок и т. д. Я до сих пор утверждаю, что это лучший способ чтения файлов в Python, больших или маленьких.

with open(...) as f:
    for line in f:
        <do something with line>

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

1 голос
/ 10 декабря 2011

Похоже, что в конце этой функции вы берете все прочитанные строки в память, а затем сразу записываете их в файл. Может быть, вы можете попробовать этот процесс:

  1. Считайте нужные строки в память (первые 3 строки).
  2. В 4-й строке добавьте строку и выполните расчет.
  3. Если вы ищете то, что искали, сбросьте значения в вашей коллекции в файл.
  4. Независимо от того, что следует, создайте новый экземпляр коллекции.

Я не пробовал это , но это может выглядеть примерно так:

o=gzip.open(file2,'w')
f=gzip.open(file1,'r'):
LIST=[]

for i,line in enumerate(f):
   if i % 4 != 3:
      LIST.append(line)
   else:
      LIST.append(line)
      b1 = [ord(x) for x in line]
      ave1 = (sum(b1) - 10) / float(len(line) - 1

      # If we've found what we want, save them to the file
      if (ave1 >= 84):
         o.writelines(LIST)

      # Release the values in the list by starting a clean list to work with
      LIST = []

РЕДАКТИРОВАТЬ: Хотя мысль, так как ваш файл очень большой, это может быть не лучшим методом из-за всех строк, которые вам придется записать в файл, но это может стоить изучить в любом случае.

0 голосов
/ 10 декабря 2011

Если вы не используете оператор with, вы должны закрыть обработчики файла:

o.close()

f.close()
0 голосов
/ 10 декабря 2011

Хорошо, вы знаете, в чем ваша проблема, уже из других комментариев / ответов, но позвольте мне просто заявить об этом.

Вы читаете только одну строку за раз в памяти, но вы сохраняетезначительная часть из них находится в памяти путем добавления в список.

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

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

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

0 голосов
/ 10 декабря 2011

Поскольку вы добавляете все строки в список LIST и только иногда удаляете некоторые строки из него, LIST мы становимся все длиннее и длиннее. Все те строки, которые вы храните в LIST, будут занимать память. Не храните все строки в списке, если вы не хотите, чтобы они занимали память.

Кроме того, ваш сценарий, кажется, нигде не производит никакого вывода, поэтому смысл всего этого не очень ясен.

...