Эффективное добавление текста в очень большой текстовый файл на языке Python


Я должен добавить некоторый произвольный текст к существующему, но очень большому (диапазон 2-10 ГБ) текстовому файлу. Поскольку файл так велик, я пытаюсь избежать чтения всего файла в память. Но не слишком ли я консервативен с построчной итерацией? Даст ли мне переход к подходу readlines (sizehint) значительное преимущество в производительности по сравнению с моим текущим подходом?

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

import os
import shutil
def prependToFile(f, text):
    f_temp = generateTempFileName(f)
    inFile  = open(f, 'r')
    outFile = open(f_temp, 'w')    
    outFile.write('# STARTn')
    outFile.write('%sn' % str(text))
    outFile.write('# ENDnn')
    for line in inFile:
        outFile.write(line)
    inFile.close()
    outFile.close()
    os.remove(f)
    shutil.move(f_temp, f)
4 2

4 ответа:

То, что вы хотите сделать, это прочитать файл в больших (от 64k до нескольких MB) блоках и записать блоки. Другими словами, вместо отдельных линий используйте огромные блоки. Таким образом, Вы делаете как можно меньше операций ввода-вывода, и, надеюсь, ваш процесс связан с вводом-выводом, а не с ЦП.

Если это на Windows NTFS, вы можете вставить в середину файла. (Или так мне сказали, я не разработчик Windows).

Если это на системе POSIX (Linux или Unix), вы должны использовать "cat", как сказал кто-то другой. кот порочно эффективен, используя каждый трюк в книге, чтобы получить оптимальную производительность (т. е. пустоты, копирующие буферы и т.д.)

Однако, если вы должны сделать это в python, представленный вами код может быть улучшен с помощью shutil.copyfileobj () (который принимает 2 дескриптора файлов) и темпфайл.TemporaryFile (создание файла, который автоматически удаляется при закрытии):

import os
import shutil
import tempfile

def prependToFile(f, text):
    outFile = tempfile.NamedTemporaryFile(dir='.', delete=False)
    outFile.write('# START\n')
    outFile.write('%s\n' % str(text))
    outFile.write('# END\n\n')
    shutil.copyfileobj(file(f, 'r'), outFile)
    os.remove(f)
    shutil.move(outFile.name, f)
    outFile.close()

Я думаю, что ОС.удалить(f) не нужно, так как шутил.move() удалит f. однако вы должны проверить это. Кроме того," delete=False " может быть не нужен, Но может быть безопасно оставить его.

Вы можете использовать инструменты, лучше подходящие для работы os.system("cat file1 file2 > file3")

Честно говоря, я бы рекомендовал вам просто написать это в C, если вы беспокоитесь о времени выполнения. Выполнение системных вызовов из Python может быть довольно медленным, и так как вам придется выполнять Много из них, независимо от того, выполняете ли вы подход построчного или необработанного чтения блоков, это действительно затянет все вниз.