2016-09-29 3 views
0

Я пишу простую программу, которая должна читать большой файл (263.5gb, если быть точным) с JSON на каждой строке (link here). Я провел некоторое исследование, и лучшим методом, который я нашел, является чтение каждой строки за строкой. Шахта выглядит следующим образом (full code here):Чтение больших текстовых файлов по-прежнему использует всю мою память

with open(dumpLocation, "r") as f: 
for line in f: 

    # Read line, convert to dictionary and assign it to 'c' 
    c = json.loads(f.readline()) 

    for n in files: 
     if n.lower() in c["title"].lower(): 

      try: 
       # Collect data 
       timestamp = str(c["retrieved_on"]) 
       sr_id = c["subreddit_id"] 
       score = str(c["score"]) 
       ups = str(c["ups"]) 
       downs = str(c["downs"]) 
       title = ('"' + c["title"] + '"') 

       # Append data to file 
       files[n].write(timestamp + "," 
           + sr_id + "," 
           + score + "," 
           + ups + "," 
           + downs + "," 
           + title + "," 
           + "\n") 
       found += 1 
      except: 
       numberOfErrors += 1 
       errors[comments] = sys.exc_info()[0] 

     comments += 1 

     # Updates user 
     print("Comments scanned: " + str(comments) + "\nFound: " + str(found) + "\n") 

Теперь я могу получить это бежать, и он побежал за хороший час, прежде чем он упал (примерно 1,3 миллиона строк). Я заметил в процессах, что использование памяти медленно растет и доходит до 2 гб перед сбоем.

Существует около 200 миллионов строк, которые мне нужно отсортировать, и я также пишу файлы, если найдены конкретные слова (в поисках 5, найдено 337 перед сбоем). Есть ли лучший способ сделать это? Мой компьютер обычно имеет только 2 Гб оперативной памяти, чтобы сэкономить

+2

Почему вы называете 'f.readline()' когда у вас уже есть строка в переменной 'line'? –

+0

Я полностью пропустил это, спасибо! Случайно оставил его там, когда я менял его. –

ответ

1

У вас есть утечка памяти здесь:

except: 
    numberOfErrors += 1 
    errors[comments] = sys.exc_info()[0] 

С огромным количеством входных линий, количество ошибок также может быть огромным, особенно если у вас есть некоторые ошибки в вашем алгоритме.

Plain except is evil, потому что он скрывает все ошибки, даже синтаксические ошибки в коде. Вы должны обрабатывать только определенные типы исключений, которые вы ожидаете от реальных данных, и сделать блок try-except максимально узким.

+0

Спасибо за быстрый ответ! У меня было ощущение, что есть что-то маленькое смешение, не зная, что это будет так ... –

+0

@TylerB Примите решение, если он решает проблему. – alexanderlukanin13

+0

Кажется, что голова как и раньше голодна и увеличивается примерно на 1,5 мб/с. –

0

Я разработал, где была утечка памяти. На этой линии, где я была печать на консоль после каждой строки:

print("Comments scanned: " + str(comments) + "\nFound: " + str(found) + "\n") 

Печать 200 миллионов раз, и ваш компьютер обязан бежать из памяти пытается держать все это в консоли сразу. Удалено, и он отлично сработал :)

+1

Как правило, ваша консоль должна иметь предел прокрутки, после которого история возрастет. Если это не так, вы можете рассмотреть вопрос об установке. Для Windows в свойствах командной строки в разделе «Макет» отрегулируйте размер буфера экрана. В Linux это сильно зависит от используемого вами конечного узла; вам нужно искать «scrollback buffer <имя вашего терминала>», чтобы выяснить, как его ограничить. – ShadowRanger

Смежные вопросы