Как правильно читать большие текстовые файлы в Python, чтобы не забивать память? - PullRequest
0 голосов
/ 12 апреля 2019

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

Я помню последние 4 символа парольной фразы, поэтому я сгенерировал список слов и хотел попытаться перехватить мой путь.Это был файл размером 4 МБ, и сценарий проверил все возможности без удачи.Потом я понял, что, возможно, буквы неправильные, но я все еще помню, какие цифры были в этих 4-х символах.Ну вдруг у меня есть 2ГБ файл, который получает SIGKILLed от Ubuntu.

Вот весь код, он очень короткий.

#!/usr/bin/python

from zipfile import ZipFile
import sys
i = 0
found = False

with ZipFile("/home/kuskus/Desktop/wallet.zip") as zf:
    with open('/home/kuskus/Desktop/wl.txt') as wordlist:
        for line in wordlist.readlines():
            if(not found):
                try:
                    zf.extractall(pwd = str.encode(line))
                    print("password found: %s" % line)
                    found = True
                except:
                    print(i)
                    i += 1
            else: sys.exit()

Я думаю, проблема в том, что текстовый файл заполняет память, поэтому ОС убивает ее.Я действительно не знаю, как я могу прочитать файл, может быть, на 1000 строк, а затем очистить его и сделать еще 1000 строк.Если бы кто-нибудь мог помочь мне, я был бы очень признателен, спасибо заранее :) Да, и текстовый файл имеет около 300 миллионов строк, если это имеет значение.

1 Ответ

3 голосов
/ 12 апреля 2019

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

with open("somefile") as fh:
     for line in fh:
         # do something

Кроме того, файловые дескрипторы позволяют вам читать определенные объемы данных, если вы выберете:

with open("somefile") as fh:
    number_of_chars = fh.read(15) # 15 is the number of characters in a StringIO style handler
    while number_of_chars:
        # do something with number_of_chars
        number_of_chars = fh.read(15)

Или, если вы хотите прочитать определенное количество строк:

with open('somefile') as fh:
    chunk_of_lines = [fh.readline() for i in range(5)] # this will read 5 lines at a time
    while chunk_of_lines:
        # do something else here
        chunk_of_lines = [fh.readline() for i in range(5)]

Где fh.readline() аналогично вызову next(fh) в цикле for.

Причина, по которой цикл while используется в последних двух примерах, заключается в том, что, как только файл будет полностью повторен, fh.readline() или fh.read(some_integer) приведут к пустой строке, которая действует как False и завершится петля

...