Хранение словарей Python

220

Я привык вводить и выводить данные в Python с помощью файлов CSV, но здесь есть очевидные проблемы. Есть ли простые способы сохранить словарь (или наборы словарей) в файле JSON или pickle ?

Например:

data = {}
data ['key1'] = "keyinfo"
data ['key2'] = "keyinfo2"

Я хотел бы знать, как это сохранить, а затем как загрузить обратно.

Майк
источник
8
Вы читали документацию по стандартным модулям json или pickle ?
Грег Хьюгилл

Ответы:

481

Рассол сохранить:

try:
    import cPickle as pickle
except ImportError:  # Python 3.x
    import pickle

with open('data.p', 'wb') as fp:
    pickle.dump(data, fp, protocol=pickle.HIGHEST_PROTOCOL)

См. Документацию модуля pickle для получения дополнительной информации относительно protocolаргумента.

Загрузка рассола :

with open('data.p', 'rb') as fp:
    data = pickle.load(fp)

Сохранение JSON :

import json

with open('data.json', 'w') as fp:
    json.dump(data, fp)

Добавьте дополнительные аргументы, например sort_keysили indent, чтобы получить хороший результат. Аргумент sort_keys сортирует ключи в алфавитном порядке, а отступ будет разделять вашу структуру данных indent=Nпробелами.

json.dump(data, fp, sort_keys=True, indent=4)

Загрузка JSON :

with open('data.json', 'r') as fp:
    data = json.load(fp)
Марти
источник
6
JSON делает словари изначально (хотя они, очевидно, не ведут себя точно так же, как словарь python, находясь в памяти, для целей сохранения они идентичны). Фактически, основной единицей в json является «Объект», который определяется как {<string>: <value>}. Выглядит знакомо? Модуль json в стандартной библиотеке поддерживает все собственные типы Python и может быть легко расширен с минимальными знаниями json для поддержки пользовательских классов. Домашняя страница JSON полностью определяет язык чуть более чем на 3 печатных страницах, поэтому ее легко усвоить / переварить.
Jonathanb
1
Стоит знать и о третьем аргументе pickle.dump. Если файл не должен быть удобочитаемым, это может значительно ускорить процесс.
Стив Джессоп
13
Если вы добавите аргументы sort_keys и indent к вызову дампа, вы получите гораздо более красивый результат. например: json.dump(data, fp, sort_keys=True, indent=4). Более подробную информацию можно найти здесь
juliusmh
1
Вы, вероятно, должны использоватьpickle.dump(data, fp, protocol=pickle.HIGHEST_PROTOCOL)
Мартин Тома
2
Для python 3 используйтеimport pickle
dangerous89
37

Минимальный пример, запись непосредственно в файл:

import json
json.dump(data, open(filename, 'wb'))
data = json.load(open(filename))

или безопасное открытие / закрытие:

import json
with open(filename, 'wb') as outfile:
    json.dump(data, outfile)
with open(filename) as infile:
    data = json.load(infile)

Если вы хотите сохранить его в строке вместо файла:

import json
json_str = json.dumps(data)
data = json.loads(json_str)
agf
источник
5

Чтобы записать в файл:

import json
myfile.write(json.dumps(mydict))

Чтобы прочитать из файла:

import json
mydict = json.loads(myfile.read())

myfile - это файловый объект для файла, в котором вы сохранили dict.

Рэйф Кеттлер
источник
1
Вы знаете, что json принимает файлы в качестве аргументов и записывает прямо в них?
1
json.dump(myfile)иjson.load(myfile)
Niklas R
5

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

myData = shelve.open('/path/to/file')

# Check for values.
keyVar in myData

# Set values
myData[anotherKey] = someValue

# Save the data for future use.
myData.close()
gddc
источник
2
Если вы хотите сохранить весь диктант или загрузить весь диктант, jsonэто удобнее. shelveлучше использовать только один ключ за раз.
agf
3

Если вам нужна альтернатива pickleили json, вы можете использовать klepto.

>>> init = {'y': 2, 'x': 1, 'z': 3}
>>> import klepto
>>> cache = klepto.archives.file_archive('memo', init, serialized=False)
>>> cache        
{'y': 2, 'x': 1, 'z': 3}
>>>
>>> # dump dictionary to the file 'memo.py'
>>> cache.dump() 
>>> 
>>> # import from 'memo.py'
>>> from memo import memo
>>> print memo
{'y': 2, 'x': 1, 'z': 3}

С klepto, если бы вы использовали serialized=True, словарь был бы записан memo.pklкак маринованный словарь, а не с открытым текстом.

Вы можете получить kleptoздесь: https://github.com/uqfoundation/klepto

dillвероятно, лучший выбор для маринования, чем pickleсамо по себе, так как dillможет сериализовать почти все в python. kleptoтакже можно использовать dill.

Вы можете получить dillздесь: https://github.com/uqfoundation/dill

Дополнительный треп в первых нескольких строках объясняется тем, что kleptoих можно настроить для хранения словарей в файле, в контексте каталога или в базе данных SQL. API одинаков для всего, что вы выбираете в качестве внутреннего архива. Это дает вам «архивируемый» словарь, с которым вы можете использовать loadи dumpвзаимодействовать с архивом.

Майк МакКернс
источник
3

Для полноты картины мы должны включить ConfigParser и configparser, которые являются частью стандартной библиотеки в Python 2 и 3 соответственно. Этот модуль читает и записывает в файл config / ini и (по крайней мере, в Python 3) ведет себя во многих отношениях как словарь. Дополнительным преимуществом является то, что вы можете хранить несколько словарей в отдельных разделах вашего файла config / ini и вызывать их. Милая!

Пример Python 2.7.x.

import ConfigParser

config = ConfigParser.ConfigParser()

dict1 = {'key1':'keyinfo', 'key2':'keyinfo2'}
dict2 = {'k1':'hot', 'k2':'cross', 'k3':'buns'}
dict3 = {'x':1, 'y':2, 'z':3}

# Make each dictionary a separate section in the configuration
config.add_section('dict1')
for key in dict1.keys():
    config.set('dict1', key, dict1[key])
   
config.add_section('dict2')
for key in dict2.keys():
    config.set('dict2', key, dict2[key])

config.add_section('dict3')
for key in dict3.keys():
    config.set('dict3', key, dict3[key])

# Save the configuration to a file
f = open('config.ini', 'w')
config.write(f)
f.close()

# Read the configuration from a file
config2 = ConfigParser.ConfigParser()
config2.read('config.ini')

dictA = {}
for item in config2.items('dict1'):
    dictA[item[0]] = item[1]

dictB = {}
for item in config2.items('dict2'):
    dictB[item[0]] = item[1]

dictC = {}
for item in config2.items('dict3'):
    dictC[item[0]] = item[1]

print(dictA)
print(dictB)
print(dictC)

Пример Python 3.X.

import configparser

config = configparser.ConfigParser()

dict1 = {'key1':'keyinfo', 'key2':'keyinfo2'}
dict2 = {'k1':'hot', 'k2':'cross', 'k3':'buns'}
dict3 = {'x':1, 'y':2, 'z':3}

# Make each dictionary a separate section in the configuration
config['dict1'] = dict1
config['dict2'] = dict2
config['dict3'] = dict3

# Save the configuration to a file
f = open('config.ini', 'w')
config.write(f)
f.close()

# Read the configuration from a file
config2 = configparser.ConfigParser()
config2.read('config.ini')

# ConfigParser objects are a lot like dictionaries, but if you really
# want a dictionary you can ask it to convert a section to a dictionary
dictA = dict(config2['dict1'] )
dictB = dict(config2['dict2'] )
dictC = dict(config2['dict3'])

print(dictA)
print(dictB)
print(dictC)

Консольный вывод

{'key2': 'keyinfo2', 'key1': 'keyinfo'}
{'k1': 'hot', 'k2': 'cross', 'k3': 'buns'}
{'z': '3', 'y': '2', 'x': '1'}

Содержимое config.ini

[dict1]
key2 = keyinfo2
key1 = keyinfo

[dict2]
k1 = hot
k2 = cross
k3 = buns

[dict3]
z = 3
y = 2
x = 1
bfris
источник
2

При сохранении в файл JSON лучший и самый простой способ сделать это:

import json
with open("file.json", "wb") as f:
    f.write(json.dumps(dict).encode("utf-8"))
Адам Лю
источник
почему это проще, чем json.dump( )указано в другом ответе?
baxx
0

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

Чтобы сохранить несколько записей в файле, необходимо проверить старое содержимое (т.е. прочитать перед записью). Типичный файл, содержащий данные JSON, будет иметь listили objectкорневой каталог. Поэтому я считал, что мой файл JSON всегда имеет, list of objectsи каждый раз, когда я добавляю в него данные, я просто сначала загружаю список, добавляю в него свои новые данные и выгружаю его обратно в доступный только для записи экземпляр file ( w):

def saveJson(url,sc): # This function writes the two values to the file
    newdata = {'url':url,'sc':sc}
    json_path = "db/file.json"

    old_list= []
    with open(json_path) as myfile:  # Read the contents first
        old_list = json.load(myfile)
    old_list.append(newdata)

    with open(json_path,"w") as myfile:  # Overwrite the whole content
        json.dump(old_list, myfile, sort_keys=True, indent=4)

    return "success"

Новый файл JSON будет выглядеть примерно так:

[
    {
        "sc": "a11",
        "url": "www.google.com"
    },
    {
        "sc": "a12",
        "url": "www.google.com"
    },
    {
        "sc": "a13",
        "url": "www.google.com"
    }
]

НОТА: Необходимо иметь файл с именем file.jsonс в []качестве исходных данных для такого подхода к работе

PS: не имеет отношения к исходному вопросу, но этот подход также можно улучшить, сначала проверив, существует ли уже наша запись (на основе одного или нескольких ключей), и только затем добавьте и сохраните данные.

Анш Сачдева
источник