Как эффективно вывести словарь в виде CSV-файла с помощью модуля Python CSV? Ошибка нехватки памяти - PullRequest
4 голосов
/ 15 июля 2010

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

Моя функция:

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 ключей), поэтому я не понимаю, почему это может привести к ошибкам памяти или быть настолько неэффективным.Требуется минуты, чтобы добраться до ошибки памяти.

спасибо за вашу помощь.

Ответы [ 4 ]

3 голосов
/ 15 июля 2010

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

  1. Выполнить итерацию по списку самостоятельно и вызвать DictWriter.writerow один раз для каждого.Хотя это будет означать много записей.
  2. Объедините строки в меньшие списки и вызовите для них DictWriter.writerows.Меньше ввода-вывода, но вы избежите выделения огромного куска памяти.
1 голос
/ 15 июля 2010

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

0 голосов
/ 15 июля 2010

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

Что такое max(len(d) for d in dictrows)?Как долго строки в диктофонах?

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

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

writer = csv.writer(.....)
for d in dictrows:
   row = [d[fieldname] for fieldname in fieldnames]
   writer.writerow(row)
0 голосов
/ 15 июля 2010

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

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...