Зберігання словників Python


198

Я звик вносити дані в Python і виходити з них .csv файлів, але для цього є очевидні проблеми. Будь-які поради щодо простих способів зберігання словника (або наборів словників) у файлі json чи pck? Наприклад:

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

Я хотів би знати як зберегти це, а потім як його знову завантажити.


8
Чи читали ви документацію для стандартних модулів json або соління ?
Грег Хьюгілл

Відповіді:


444

Зберегти соління :

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)

Дивіться модуль документацію розсолу для отримання додаткової інформації щодо 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)

4
JSON виконує словники на самому собі (хоча вони, очевидно, не так поводяться, як словник python, будучи в пам'яті, для постійності вони однакові). Фактично, основоположною одиницею в json є "Об'єкт", який визначається як {<string>: <значення>}. Вигляд знайомий? Модуль json у стандартній бібліотеці підтримує кожен рідний тип Python і легко може бути розширений з мінімальними знаннями json для підтримки визначених користувачем класів. Домашня сторінка JSON повністю визначає мову лише у понад 3 друкованих сторінках, тому її легко засвоїти / перетравити.
Джонатанб

1
Варто знати і про третій аргумент pickle.dump. Якщо файл не потрібно читати людиною, то він може значно прискорити роботу.
Стів Джессоп

11
Якщо ви додасте sort_keys та відступи від аргументів до дамп-дзвінка, ви отримаєте набагато красивіший результат. наприклад: json.dump(data, fp, sort_keys=True, indent=4). Більше інформації можна знайти тут
juliusmh

1
Мабуть, ви повинні використовуватиpickle.dump(data, fp, protocol=pickle.HIGHEST_PROTOCOL)
Мартін Тома

1
Для python 3 використовуйтеimport pickle
небезпека89

35

Мінімальний приклад, запис безпосередньо у файл:

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)


5

Щоб написати у файл:

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

Щоб прочитати з файлу:

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

myfile - це об'єкт файлу для файлу, в якому ви зберігали дикт.


Ви знаєте, що json має файли як аргументи і записує їх безпосередньо?

json.dump(myfile)іjson.load(myfile)
Ніклас Р

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()

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

Додатковий mumbo-jumbo в перших кількох рядках полягає в тому, що він 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 config
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 config to file
f = open('config.ini', 'w')
config.write(f)
f.close()

# read config from 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 config
config['dict1'] = dict1
config['dict2'] = dict2
config['dict3'] = dict3

# save config to file
f = open('config.ini', 'w')
config.write(f)
f.close()

# read config from 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

1

Якщо зберегти у файлі 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і кожного разу, коли я додаю в нього дані, я просто спочатку завантажую список, додаю в нього свої нові дані та скидаю їх назад до записуваного лише примірника файлу ( w):

def saveJson(url,sc): #this function writes the 2 values to 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 "sucess"

новий файл json буде виглядати приблизно так:

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

Примітка: Необхідно мати файл з ім'ям file.jsonз в []якості вихідних даних для такого підходу до роботи

PS: не пов’язано з оригінальним запитанням, але цей підхід також можна було б покращити, попередньо перевіривши, чи існує наша запис (заснована на 1 / декількох клавішах), а потім додавати та зберігати дані. Дайте мені знати, якщо комусь потрібна ця перевірка, я додам до відповіді

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.