2010-07-14 1 views
4

Я пытаюсь сериализовать список словарей в текстовый файл csv с помощью модуля CSV Python. В моем списке около 13 000 элементов, каждый из которых - словарь с ~ 100 ключами, состоящими из простого текста и цифр. Моя функция «dictlist2file» просто вызывает DictWriter для сериализации этого, но я получаю ошибки в памяти.Как эффективно выводить словарь как файл csv с помощью модуля csv Python? Ошибка в памяти

Моя функция:

def dictlist2file(dictrows, filename, fieldnames, delimiter='\t', 
        lineterminator='\n', extrasaction='ignore'): 
    out_f = open(filename, 'w') 

    # Write out header 
    if fieldnames != None: 
     header = delimiter.join(fieldnames) + lineterminator 
    else: 
     header = dictrows[0].keys() 
     header.sort() 
    out_f.write(header) 

    print "dictlist2file: serializing %d entries to %s" \ 
      %(len(dictrows), filename) 
    t1 = time.time() 
    # Write out dictionary 
    data = csv.DictWriter(out_f, fieldnames, 
       delimiter=delimiter, 
       lineterminator=lineterminator, 
          extrasaction=extrasaction) 
    data.writerows(dictrows) 
    out_f.close() 
    t2 = time.time() 
    print "dictlist2file: took %.2f seconds" %(t2 - t1) 

Когда я попробовать это на моем словаре, я получаю следующий результат:

dictlist2file: serializing 13537 entries to myoutput_file.txt 
Python(6310) malloc: *** mmap(size=45862912) failed (error code=12) 
*** error: can't allocate region 
*** set a breakpoint in malloc_error_break to debug 
Traceback (most recent call last): 
... 
    File "/Library/Frameworks/Python.framework/Versions/6.2/lib/python2.6/csv.py", line 149, in writerows 
    rows.append(self._dict_to_list(rowdict)) 
    File "/Library/Frameworks/Python.framework/Versions/6.2/lib/python2.6/csv.py", line 141, in _dict_to_list 
    return [rowdict.get(key, self.restval) for key in self.fieldnames] 
MemoryError 

Любая идея, что может быть причиной этого? Список содержит всего 13 000 элементов, а сами словари очень простые и маленькие (100 ключей), поэтому я не понимаю, почему это приведет к ошибкам памяти или будет настолько неэффективным. Для получения ошибки памяти требуется несколько минут.

благодарит за вашу помощь.

ответ

0

У меня нет ответа на то, что происходит с CSV, но я обнаружил, что следующий заменить сериализует словарь в файл менее чем за несколько секунд:

for row in dictrows: 
    out_f.write("%s%s" %(delimiter.join([row[name] for name in fieldnames]), 
         lineterminator)) 

где dictrows является генератор словарей, созданных DictReader из csv, fieldnames - это список полей.

Любая идея о том, почему csv не выполняет аналогичные действия, будет очень признательна. Благодарю.

1

Вы можете отключить внутреннюю проблему Python. Я бы сообщил об этом на bugs.python.org.

3

DictWriter.writerows(...)DictWriter.writerows(...) принимает все данные, которые вы передаете ему, и создает (в памяти) весь новый список списков, по одному для каждой строки. Поэтому, если у вас много данных, я вижу, как появится MemoryError. Два способа вы можете продолжить:

  1. Идите по списку самостоятельно и позвоните по номеру DictWriter.writerow один раз для каждого. Хотя это будет означать много писем.
  2. Запуск строк в меньшие списки и вызов DictWriter.writerows для них. Меньше ввода-вывода, но вы избегаете выделения огромного объема памяти.
+0

Использование: для строки в dictrows: данные.writerow (row) не имеет значения. Я не понимаю, почему проблема памяти - это всего 13 000 словарей, и каждый из них по-прежнему довольно мал и вообще не вложен. Он содержит только строки и числа ... есть ли альтернатива модулю csv, который менее медленный? – user248237dfsf

0

Вы говорите, что если вы зацикливаете на data.writerow (single_dict), что проблема по-прежнему возникает. Поместите код, чтобы показать количество строк каждые 100 строк. Сколько dicts оно обработало прежде чем оно получает ошибку памяти? Запускайте больше или меньше процессов, чтобы впитать больше или меньше памяти ... не так ли место, где оно терпит неудачу?

Что такое max(len(d) for d in dictrows)? Сколько строк в dicts?

Сколько у вас свободной памяти?

Обновление: Посмотрите, есть ли проблема с Dictwriter; устранить его и использовать основные функциональные возможности CSV:

writer = csv.writer(.....) 
for d in dictrows: 
    row = [d[fieldname] for fieldname in fieldnames] 
    writer.writerow(row) 
Смежные вопросы