Python: хранение больших структур данных

1

В настоящее время я делаю проект на питоне, который использует словари, которые относительно большие (около 800 МБ). Я попытался сохранить один из этих словарей, используя pickle, но получил MemoryError.

Каков правильный способ сохранения таких файлов в python? Должен ли я использовать базу данных?

  • 0
    Это зависит от того, что вы храните в этих словарях. Возможно, модуль json - это альтернатива, которую вы можете легко попробовать ( import json; json.dumps(mydict) и посмотрите, не появляется ли такая же ошибка).
  • 0
    Просто сбросьте данные в файл CSV. Я успешно сделал это для файлов размером до 3 ГБ
Показать ещё 3 комментария
Теги:
data-structures
pickle

5 ответов

2
Лучший ответ

Python-standard shelve модуль предоставляет диктофонный интерфейс для постоянных объектов. Он работает со многими базами данных и не ограничен оперативной памятью. Преимущество использования shelve над прямой работой с базами данных заключается в том, что большая часть вашего существующего кода остается такой, какая была. Это происходит за счет скорости (по сравнению с операционными операциями) и за счет гибкости (по сравнению с работой непосредственно с базами данных).

  • 0
    Я использовал полку, так как это потребовало минимального изменения кода. Спасибо.
0

В отличие от shelf, klepto не нужно хранить весь dict в одном файле (использование одного файла очень медленное для чтения-записи, когда вам нужна только одна запись). Кроме того, в отличие от shelf, klepto может хранить почти любой тип объекта python, который вы можете поместить в словарь (вы можете хранить функции, lambdas, экземпляры классов, сокеты, очереди многопроцессорности, что угодно).

klepto предоставляет абстракцию словаря для записи в базу данных, включая обработку вашей файловой системы как базы данных (т.е. запись всего словаря в один файл или запись каждой записи в его собственный файл). Для больших данных я часто предпочитаю представлять словарь как каталог в моей файловой системе и каждый из них должен быть файлом. klepto также предлагает множество алгоритмов кэширования (например, mru, lru, lfu и т.д.), чтобы помочь вам управлять кешем в памяти и будет использовать алгоритм для создания дампа и загрузки в архивную базу для вас.

>>> from klepto.archives import dir_archive
>>> d = {'a':1, 'b':2, 'c':map, 'd':None}
>>> # map a dict to a filesystem directory
>>> demo = dir_archive('demo', d, serialized=True) 
>>> demo['a']
1
>>> demo['c']
<built-in function map>
>>> demo          
dir_archive('demo', {'a': 1, 'c': <built-in function map>, 'b': 2, 'd': None}, cached=True)
>>> # is set to cache to memory, so use 'dump' to dump to the filesystem 
>>> demo.dump()
>>> del demo
>>> 
>>> demo = dir_archive('demo', {}, serialized=True)
>>> demo
dir_archive('demo', {}, cached=True)
>>> # demo is empty, load from disk
>>> demo.load()
>>> demo
dir_archive('demo', {'a': 1, 'c': <built-in function map>, 'b': 2, 'd': None}, cached=True)
>>> demo['c']
<built-in function map>
>>> 

klepto также обеспечивает использование обращенных к памяти файлов, для быстрого чтения-записи. Существуют и другие флаги, такие как compression, которые можно использовать для дальнейшей настройки того, как хранятся ваши данные. Не менее просто (тот же самый точный интерфейс) использовать базу данных (MySQL и т.д.) В качестве бэкэнд вместо вашей файловой системы. Вы можете использовать флаг cached=False, чтобы полностью отключить кеширование памяти, а также напрямую читать и записывать на диск и из базы данных и обратно.

>>> from klepto.archives import dir_archive
>>> # does not hold entries in memory, each entry will be stored on disk
>>> demo = dir_archive('demo', {}, serialized=True, cached=False)
>>> demo['a'] = 10
>>> demo['b'] = 20
>>> demo['c'] = min
>>> demo['d'] = [1,2,3]

Получить klepto здесь: https://github.com/uqfoundation

0

Возможно, вы могли бы использовать sqlite3? Если у вас нет реальной старой версии Python, она должна быть доступна: https://docs.python.org/2/library/sqlite3.html

Я не проверял ограничения sqlite3, и я не знаю его полезности в вашей ситуации, но было бы полезно проверить.

  • 0
    Я думал об этом, но нужно будет немного изменить код. Спасибо за предложение, хотя.
0

Когда вы распиливаете всю структуру данных, вы ограничены системной памятью. Вы можете, однако, сделать это в кусках.

streaming-pickle выглядит как решение для травления файловых объектов, больших, чем память на борту.

https://gist.github.com/hardbyte/5955010

-1

Так как это словарь, вы можете преобразовать его в список пар значений ключа ([(k, v)]). Затем вы можете сериализовать каждый кортеж в строку с помощью любой технологии, которая вам нужна (например, pickle), и хранить их в файле по строкам. Таким образом, процесс распараллеливания, проверка содержимого файла и т.д. Также проще.

Есть библиотеки, которые позволяют вам передавать отдельные объекты, но IMO это просто усложняет. Простое хранение строки за строкой удаляет столько головной боли.

  • 0
    да, даунвот? Почему?
  • 0
    Я думаю, что это усложняется, когда Shelve делает это уже.
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню