Как удалить строки из большого файла в Python, в ограниченной среде - PullRequest
6 голосов
/ 17 декабря 2010

Скажем, у меня есть Ubuntu VPS на 10 ГБ в США (и я живу в некоторых других странах), и у меня есть текстовый файл на 9 ГБ на жестком диске.У меня 512 МБ ОЗУ и примерно столько же объема подкачки.

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

Ответы [ 5 ]

3 голосов
/ 17 декабря 2010

Как насчет этого?Он редактирует файл на месте.Я протестировал его на некоторых небольших текстовых файлах (в Python 2.6.1), но я не уверен, насколько хорошо он будет работать с массивными файлами из-за всех скачков, но все же ...

Я использовал неопределенный цикл while с ручной проверкой EOF, потому что for line in f: не работал правильно (предположительно, все прыжки нарушали нормальную итерацию).Возможно, есть лучший способ проверить это, но я относительно новичок в Python, поэтому кто-то, пожалуйста, дайте мне знать, если есть.

Также вам нужно определить функцию isRequired(line).

writeLoc = 0
readLoc = 0
with open( "filename" , "r+" ) as f:
    while True:
        line = f.readline()

        #manual EOF check; not sure of the correct
        #Python way to do this manually...
        if line == "":
            break

        #save how far we've read
        readLoc = f.tell()

        #if we need this line write it and
        #update the write location
        if isRequired(line):
            f.seek( writeLoc )
            f.write( line )
            writeLoc = f.tell()
            f.seek( readLoc )

    #finally, chop off the rest of file that's no longer needed
    f.truncate( writeLoc )
2 голосов
/ 17 декабря 2010

Попробуйте:

currentReadPos = 0
removedLinesLength = 0
for line in file:
    currentReadPos = file.tell()
    if remove(line):
        removedLinesLength += len(line)
    else:
        file.seek(file.tell() - removedLinesLength)
        file.write(line + "\n")
        file.flush()
    file.seek(currentReadPos)

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

1 голос
/ 17 декабря 2010

Обновление

Я попытался fileinput с на месте , создав файл объемом 1 ГБ. То, что я ожидал, отличалось от того, что случилось. На этот раз я правильно прочитал документацию.

Дополнительная фильтрация на месте: если аргумент ключевого слова inplace = 1 передан к fileinput.input () или к FileInput конструктор, файл перешел на резервный файл и стандарт вывод направляется во входной файл (если файл с тем же именем, что и резервный файл уже существует, он будет заменил молча).

из docs / fileinput

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


Перед редактированием:

Если вы ищете для редактирования файла inplace , то проверьте модуль Python fileinput - Docs .

Я действительно не уверен в его эффективности при использовании с файлом 10 ГБ. Но мне показалось, что это единственный вариант, который вы используете с помощью Python.

0 голосов
/ 17 декабря 2010

Обработка файла с получением 10/20 или более МБ блоков.Это был бы самый быстрый способ.

Другой способ сделать это - потоковая передача этого файла и его фильтрация с использованием, например, AWK.

пример псевдокода:

file = open(rw)
linesCnt=50
newReadOffset=0
tmpWrtOffset=0
rule=1
processFile()
{
  while(rule)
  {
      (lines,newoffset)=getLines(file, newReadOffset)
      if lines:
          [x for line in lines if line==cool: line]
          tmpWrtOffset = writeBackToFile(file, x, tmpWrtOffset) #should return new offset to write for the next time
      else:
          rule=0
  }
}

Чтобы изменить размер файла в конце, используйтене усечение (размер = None)

0 голосов
/ 17 декабря 2010

Просто последовательно читайте и записывайте в файлы.

f.readlines () возвращает список содержащий все строки данных в файл. Если дан необязательный параметр sizehint, он читает, что многие байтов из файла и достаточно больше, чтобы завершить строку и возвращает строки От этого. Это часто используется для разрешения эффективное чтение большого файла линии, но без необходимости загружать весь файл в памяти. только полный строки будут возвращены.

Источник

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...