Самый простой способ сохранить структуру данных в файл в python?

Скажем, у меня есть что-то вроде этого:

d = { "abc" : [1, 2, 3], "qwerty" : [4,5,6] }

Какой самый простой способ программно получить это в файл, который я могу загрузить из python позже?

Могу ли я каким-то образом сохранить его как источник Python (из скрипта Python, а не вручную!), а затем import позже?

Или я должен использовать JSON или что-то в этом роде?


person Blorgbeard    schedule 26.06.2009    source источник
comment
Вот еще пара: набор данных и jsonpickle.   -  person zekel    schedule 26.03.2016
comment
Самый простой способ - это JSON, потому что он структурирует данные, подобные словарю Python. К счастью, у python есть встроенный модуль JSON. Все, что вам нужно сделать, это просто import json.   -  person Willy satrio nugroho    schedule 25.12.2020


Ответы (7)


Используйте модуль pickle.

import pickle
d = { "abc" : [1, 2, 3], "qwerty" : [4,5,6] }
afile = open(r'C:\d.pkl', 'wb')
pickle.dump(d, afile)
afile.close()

#reload object from file
file2 = open(r'C:\d.pkl', 'rb')
new_d = pickle.load(file2)
file2.close()

#print dictionary object loaded from file
print new_d
person eric.christensen    schedule 26.06.2009
comment
Что означает буква r перед путем? - person Blorgbeard; 26.06.2009
comment
Кроме того, это дает мне TypeError: не может записывать байты в текстовый поток - отличается ли он для Python 3.0? - person Blorgbeard; 26.06.2009
comment
r'' обозначает необработанную строку, описанную здесь: docs.python.org/ reference/lexical_analysis.html#string-literals. По сути, это означает, что обратная косая черта в строке включается как буквальная обратная косая черта, а не экранирование символов (хотя необработанная строка не может заканчиваться обратной косой чертой). - person Miles; 26.06.2009
comment
Я исправил пример — файл нужно открывать в бинарном режиме. Это все еще должно быть для Python 2, но это не приведет к такому резкому сбою. - person Miles; 26.06.2009
comment
Убедитесь, что вы прочитали документацию по Python (в том числе для соответствующей версии), а не просто полагаетесь на примеры! :) docs.python.org/3.0/library/pickle.html ( Извините за спам в комментариях!) - person Miles; 26.06.2009
comment
Я сомневаюсь в этом, поскольку ваш исходный пример не открывал файл в режиме записи. ;) Но что касается двоичного режима, в Python 2 он может работать (поскольку двоичный флаг практически не влияет на Linux и OS X), но он не переносим и может столкнуться с проблемами в Windows, если результирующий файл содержит новую строку или EOF-символы DOS. - person Miles; 26.06.2009
comment
Технически травление будет работать для файлов текстового режима, если вы не используете двоичный формат травления (т.е. протокол = 0) и используете его последовательно (т.е. также используете текстовый режим для обратного чтения). Однако использование двоичного кода, как правило, является лучшей идеей, особенно если вы можете перемещать данные между платформами. - person Brian; 26.06.2009

Выбирайте: Стандартная библиотека Python — сохранение данных. Какой из них наиболее подходит, может варьироваться в зависимости от ваших конкретных потребностей.

pickle, вероятно, является самым простым и наиболее способным, поскольку "записывает произвольный объект в файл и восстановить его» — он может автоматически обрабатывать пользовательские классы и циклические ссылки.

Для лучшей производительности травления (скорость и пространство) используйте cPickle на HIGHEST_PROTOCOL.

person Miles    schedule 26.06.2009

Попробуйте модуль полки, который даст вам постоянный словарь, например:

import shelve
d = { "abc" : [1, 2, 3], "qwerty" : [4,5,6] }

shelf = shelve.open('shelf_file')
for key in d:
    shelf[key] = d[key]

shelf.close()

....

# reopen the shelf
shelf = shelve.open('shelf_file')
print(shelf) # => {'qwerty': [4, 5, 6], 'abc': [1, 2, 3]}
person mhawke    schedule 26.06.2009

JSON имеет недостатки, но когда он соответствует вашим потребностям, он также:

  • простой в использовании
  • включен в стандартную библиотеку как модуль json
  • интерфейс чем-то похож на pickle, который может обрабатывать более сложные ситуации
  • редактируемый человеком текст для отладки, совместного использования и контроля версий
  • действительный код Python
  • хорошо зарекомендовал себя в Интернете (если ваша программа касается какой-либо из этих областей)
person Community    schedule 26.06.2009
comment
JSON не является допустимым Python. На первый взгляд это выглядит так, но используйте некоторые логические значения, и вы увидите проблему (JSON использует true и false, а Python использует True и False). Также: массивы JSON (dicts) имеют только строковые ключи. Таким образом, он не сохраняет структуру данных правильно. - person Jürgen A. Erhard; 17.06.2013

Вы также можете взглянуть на базу данных объектов Zope, чем сложнее вы становитесь: - ) Вероятно, слишком много для того, что у вас есть, но оно хорошо масштабируется и не слишком сложно в использовании.

person Jay Atkinson    schedule 26.06.2009

Если вы хотите сохранить его в удобном для чтения формате, похожем на JSON, используйте repr для сериализации объекта и eval для его десериализации.

repr(object) -> string

Возвращает каноническое строковое представление объекта. Для большинства типов объектов eval(repr(object)) == object.

person John Kugelman    schedule 26.06.2009
comment
Рассмотрим ast.literal_eval() (docs.python.org/library/ast.html #ast.literal_eval) в качестве альтернативы eval(). - person Miles; 26.06.2009
comment
Главное, что мне не нравится в этом решении, это то, что у вас есть объект в структуре, в которой идентификатор eval(repr()) не сохраняется, repr() завершится успешно, но затем eval() будет блевать. - person Miles; 26.06.2009
comment
@John Джон, ты будешь наказан за этот ответ ... где С.Лотт? - person mhawke; 26.06.2009
comment
pickle, YAML, JSON и т. д. безопаснее и работают с большим количеством типов, чем этот метод. ИМО, eval() следует избегать, когда это возможно. - person Jason Creighton; 26.06.2009
comment
Хех, я должен был знать, что надел свои асбестовые штаны, прежде чем предлагать eval! Это честный полицейский. - person John Kugelman; 26.06.2009
comment
@Jason: На самом деле, pickle ничуть не безопаснее, чем eval — вредоносный ввод может так же легко выполнять код, и здесь, по крайней мере, очевидно, что он это делает, поэтому я думаю, что голосование против этого немного несправедливо. Есть и другие причины, по которым следует избегать eval() (например, обрабатывает только объекты с evalable repr() и молча теряет данные, если они не самооцениваются, как указал Майлз), но с точки зрения безопасности это не хуже, чем рассола. - person Brian; 26.06.2009
comment
@Brian: Хороший вопрос, я не подумал об этом. Но дело в том, что из перечисленных мной альтернатив pickle и YAML работают с большим количеством типов данных, чем repr()/eval(), а YAML и JSON безопаснее. Так что я все еще думаю, что eval() здесь плохая идея. - person Jason Creighton; 26.06.2009