Stockage de dictionnaires Python

198

J'ai l'habitude de faire entrer et sortir des données de Python en utilisant des fichiers .csv, mais il y a des défis évidents à cela. Des conseils sur les moyens simples de stocker un dictionnaire (ou des ensembles de dictionnaires) dans un fichier json ou pck? Par exemple:

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

Je voudrais savoir comment l'enregistrer, puis comment le charger à nouveau.

Mike
la source
8
Avez-vous lu la documentation des modules standard json ou pickle ?
Greg Hewgill

Réponses:

443

Pickle save:

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)

Voir la documentation du module pickle pour plus d'informations sur l' protocolargument.

Charge de cornichon :

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

Sauvegarde JSON :

import json

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

Fournissez des arguments supplémentaires comme sort_keysou indentpour obtenir un joli résultat. L'argument sort_keys triera les clés par ordre alphabétique et le retrait mettra en retrait votre structure de données avec des indent=Nespaces.

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

Charge JSON :

with open('data.json', 'r') as fp:
    data = json.load(fp)
Marty
la source
4
JSON fait les dictionnaires nativement (bien qu'ils ne se comportent évidemment pas exactement comme le fait un dictionnaire python en mémoire, à des fins de persistance, ils sont identiques). En fait, l'unité fondamentale dans json est l '"objet", qui est défini comme {<chaîne>: <valeur>}. Semble familier? Le module json de la bibliothèque standard prend en charge tous les types natifs Python et peut facilement être étendu avec une connaissance minimale de json pour prendre en charge les classes définies par l'utilisateur. La page d'accueil JSON définit complètement la langue en un peu plus de 3 pages imprimées, il est donc facile à absorber / à digérer rapidement.
Jonathanb
1
Il convient également de connaître le troisième argument pickle.dump. Si le fichier n'a pas besoin d'être lisible par l'homme, cela peut accélérer considérablement les choses.
Steve Jessop
11
Si vous ajoutez sort_keys et tiret arguments à l'appel de décharge , vous obtenez un résultat beaucoup plus joli de. par exemple: json.dump(data, fp, sort_keys=True, indent=4). Plus d'informations peuvent être trouvées ici
juliusmh
1
Vous devriez probablement utiliserpickle.dump(data, fp, protocol=pickle.HIGHEST_PROTOCOL)
Martin Thoma
1
Pour python 3, utilisezimport pickle
danger89
35

Exemple minimal, écrivant directement dans un fichier:

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

ou ouverture / fermeture en toute sécurité:

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

Si vous souhaitez l'enregistrer dans une chaîne au lieu d'un fichier:

import json
json_str = json.dumps(data)
data = json.loads(json_str)
agf
la source
5

Pour écrire dans un fichier:

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

Pour lire à partir d'un fichier:

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

myfile est l'objet fichier du fichier dans lequel vous avez stocké le dict.

Rafe Kettler
la source
vous êtes un logiciel que json utilise pour prendre des fichiers en argument et y écrire directement?
json.dump(myfile)etjson.load(myfile)
Niklas R
5

Si vous êtes après la sérialisation mais n'avez pas besoin des données dans d'autres programmes, je recommande fortement le shelvemodule. Considérez-le comme un dictionnaire persistant.

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
la source
2
Si vous souhaitez stocker un dict entier ou charger un dict entier, jsonc'est plus pratique. shelven'est meilleur que pour accéder à une clé à la fois.
agf
3

Si vous souhaitez une alternative à pickleou json, vous pouvez utiliser 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}

Avec klepto, si vous l'aviez utilisé serialized=True, le dictionnaire aurait été écrit memo.pklcomme un dictionnaire mariné au lieu d'un texte clair.

Vous pouvez obtenir kleptoici: https://github.com/uqfoundation/klepto

dillest probablement un meilleur choix pour le décapage que lui- picklemême, car il dillpeut sérialiser presque tout en python. kleptopeut également utiliser dill.

Vous pouvez obtenir dillici: https://github.com/uqfoundation/dill

Le mumbo-jumbo supplémentaire sur les premières lignes est dû au fait qu'il kleptopeut être configuré pour stocker des dictionnaires dans un fichier, dans un contexte de répertoire ou dans une base de données SQL. L'API est la même pour tout ce que vous choisissez comme archive principale. Il vous donne un dictionnaire "archivable" avec lequel vous pouvez utiliser loadet dumpinteragir avec l'archive.

Mike McKerns
la source
3

Il s'agit d'un ancien sujet, mais pour être complet, nous devons inclure ConfigParser et configparser qui font partie de la bibliothèque standard en Python 2 et 3, respectivement. Ce module lit et écrit dans un fichier config / ini et (au moins en Python 3) se comporte de nombreuses manières comme un dictionnaire. Il a l'avantage supplémentaire que vous pouvez stocker plusieurs dictionnaires dans des sections distinctes de votre fichier config / ini et les rappeler. Doux!

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

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

sortie console

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

contenu de config.ini

[dict1]
key2 = keyinfo2
key1 = keyinfo

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

[dict3]
z = 3
y = 2
x = 1
bfris
la source
1

Si vous enregistrez dans un fichier json, la manière la meilleure et la plus simple de procéder est:

import json
with open("file.json", "wb") as f:
    f.write(json.dumps(dict).encode("utf-8"))
Adam Liu
la source
pourquoi est-ce plus facile que json.dump( )celui décrit dans l'autre réponse?
baxx
0

mon cas d'utilisation consistait à enregistrer plusieurs objets json dans un fichier et la réponse de marty m'a un peu aidé. Mais pour répondre à mon cas d'utilisation, la réponse n'était pas complète car elle remplacerait les anciennes données chaque fois qu'une nouvelle entrée est enregistrée.

Pour enregistrer plusieurs entrées dans un fichier, il faut vérifier l'ancien contenu (c'est-à-dire lire avant d'écrire). Un fichier typique contenant des données json aura un listou un objectcomme racine. J'ai donc considéré que mon fichier json a toujours un list of objectset chaque fois que j'ajoute des données, je charge simplement la liste en premier, y ajoute mes nouvelles données et les renvoie dans une instance de file ( w) accessible en écriture uniquement :

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"

le nouveau fichier json ressemblera à ceci:

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

REMARQUE: il est essentiel d'avoir un fichier nommé file.jsonavec []comme données initiales pour que cette approche fonctionne

PS: pas lié à la question d'origine, mais cette approche pourrait également être encore améliorée en vérifiant d'abord si notre entrée existe déjà (sur la base de 1 / plusieurs clés) et ensuite seulement ajouter et enregistrer les données. Faites-moi savoir si quelqu'un a besoin de cette vérification, je vais ajouter à la réponse

ansh sachdeva
la source