Pythonic способ обработки 200 миллионов элементов данных?

У меня есть каталог из 1000 файлов. В каждом файле есть много строк, где каждая строка представляет собой ngram размером от 4 до 8 байт. Я пытаюсь проанализировать все файлы, чтобы получить отдельные нграммы в виде строки заголовка, а затем для каждого файла я хочу написать строку, в которой есть частота этой последовательности нграмм, встречающейся в файле.

Следующий код сделал это путем сбора заголовков, но при попытке записать заголовки в файл csv произошла ошибка памяти. Я запускал его на экземпляре Amazon EC2 с 30 ГБ оперативной памяти. Кто-нибудь может дать рекомендации по оптимизации, о которых я не знаю?

#Note: A combination of a list and a set is used to maintain order of metadata
#but still get performance since non-meta headers do not need to maintain order
header_list = []
header_set = set()
header_list.extend(META_LIST)
for ngram_dir in NGRAM_DIRS:
  ngram_files = os.listdir(ngram_dir)
  for ngram_file in ngram_files:      
      with open(ngram_dir+ngram_file, 'r') as file:
        for line in file:
          if not '.' in line and line.rstrip('\n') not in IGNORE_LIST:
            header_set.add(line.rstrip('\n'))

header_list.extend(header_set)#MEMORY ERROR OCCURRED HERE

outfile = open(MODEL_DIR+MODEL_FILE_NAME, 'w')
csvwriter = csv.writer(outfile)
csvwriter.writerow(header_list)

#Convert ngram representations to vector model of frequencies
for ngram_dir in NGRAM_DIRS:
  ngram_files = os.listdir(ngram_dir)
  for ngram_file in ngram_files:      
      with open(ngram_dir+ngram_file, 'r') as file:
        write_list = []
        linecount = 0
        header_dict = collections.OrderedDict.fromkeys(header_set, 0)
        while linecount < META_FIELDS: #META_FIELDS = 3
          line = file.readline()
          write_list.append(line.rstrip('\n'))
          linecount += 1 
        file_counter = collections.Counter(line.rstrip('\n') for line in file)
        header_dict.update(file_counter)
        for value in header_dict.itervalues():
          write_list.append(value)
        csvwriter.writerow(write_list)

outfile.close() 

1 ответ

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

Вместо этого:

header_list.extend(header_set)#MEMORY ERROR OCCURRED HERE

Сделайте это (при условии, что csvwriter.writerow принимает любой итератор):

headers = itertools.chain(header_list, header_set)
...
csvwriter.writerow(headers)

Это должно по крайней мере избежать проблемы с памятью, которую вы сейчас видите.

Другие вопросы по тегам