Как мне правильно читать большие текстовые файлы в Python, чтобы не засорять память?

#python #file #large-files

#python #файл #большие файлы

Вопрос:

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

Я помню последние 4 символа ключевой фразы, поэтому я сгенерировал список слов и хотел попробовать применить к нему грубую силу. Это был файл размером 4 МБ, и сценарий безуспешно проверил все возможности. Затем я понял, что, возможно, буквы неправильные, но я все еще помню, какие числа были в этих 4 символах. Ну, внезапно у меня есть файл объемом 2 ГБ, который загружается 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. Сколько у вас оперативной памяти?

2. readlines() создает список из файла, поэтому весь файл будет находиться в памяти. Если вы измените это значение for line in wordlist только на одну строку, файл будет загружаться в память одновременно.

3. Всего 4 ГБ. Без создания списка это работает как шарм. Теперь я надеюсь, что он найдет это. Спасибо!

Ответ №1:

Обычно лучшее, что можно сделать, это выполнить итерацию по файлу напрямую. Обработчик файлов будет действовать как генератор, создавая строки по одной за раз, а не объединяя их все сразу в память в список (как 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:
    while True:
        chunk_of_lines = [fh.readline() for i in range(5)] # this will read 5 lines at a time
        if not chunk_of_lines:
            break
        # do something else here
  

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

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