web-dev-qa-db-fra.com

Comment cPickle dump et charger des dictionnaires séparés dans le même fichier?

J'ai un processus qui s'exécute et crée trois dictionnaires: 2 plutôt petits et 1 grand.

Je sais que je peux stocker un dictionnaire comme:

import cPickle as pickle
with open(filename, 'wb') as fp:
  pickle.dump(self.fitResults, fp)

Ce que j'aimerais faire, c'est stocker les 3 dictionnaires dans le même fichier, avec la possibilité de charger les trois dictionnaires séparément à un autre moment. Quelque chose comme

with open(filename, 'rb') as fp:
  dict1, dict2, dict3 = pickle.load(fp)

Ou mieux encore, il suffit de charger les deux premiers dictionnaires et de choisir de charger le troisième (grand). Est-ce possible ou dois-je procéder d'une manière complètement différente?

17
JBWhitmore

Bien sûr, il vous suffit de vider chacun d'eux séparément, puis de les charger séparément:

with open(filename,'wb') as fp:
    pickle.dump(dict1,fp)
    pickle.dump(dict2,fp)
    pickle.dump(dict3,fp)

with open(filename,'rb') as fp:
    d1=pickle.load(fp)
    d2=pickle.load(fp)
    d3=pickle.load(fp)

assurez-vous de vider le gros en dernier afin de pouvoir charger les petits sans charger le gros en premier. J'imagine que vous pourriez même devenir intelligent et stocker les positions de fichier où chaque vidage commence dans une sorte d'en-tête, puis vous pouvez rechercher cet emplacement avant le chargement (mais cela commence à devenir un peu plus compliqué).

24
mgilson

Je recommande le module souvent oublié shelve qui vous fournit efficacement un dictionnaire persistant soutenu par un fichier Berkley DB ou un fichier dbm (tel que sélectionné par anydbm). La base de données devrait fournir des améliorations de performances (pour votre gros dictionnaire).

Exemple d'utilisation:

import shelve
shelf = shelve.open('my_shelf')
>>> shelf
{}

# add your dictionaries (or any pickleable objects)
shelf['dict1'] = dict(a=10, b=20, c=30, l=[10, 20, 30])
shelf['dict2'] = dict(a=100, b=200, c=300, l=[100, 200, 300])
shelf['dict3'] = dict(a=1000, b=2000, c=3000, l=[1000, 2000, 3000])

>>> shelf
{'dict1': {'a': 10, 'c': 30, 'b': 20, 'l': [10, 20, 30]}, 'dict3': {'a': 1000, 'c': 3000, 'b': 2000, 'l': [1000, 2000, 3000]}, 'dict2': {'a': 100, 'c': 300, 'b': 200, 'l': [100, 200, 300]}}
shelf.close()

# then, later
shelf = shelve.open('my_shelf')
>>> shelf
{'dict1': {'a': 10, 'c': 30, 'b': 20, 'l': [10, 20, 30]}, 'dict3': {'a': 1000, 'c': 3000, 'b': 2000, 'l': [1000, 2000, 3000]}, 'dict2': {'a': 100, 'c': 300, 'b': 200, 'l': [100, 200, 300]}}
6
mhawke

Comme mentionné ici , vous pouvez décaper plusieurs objets dans le même fichier et les charger tous (dans le même ordre):

f = file(filename, 'wb')
for obj in [dict1, dict2, dict3]:
    cPickle.dump(obj, f, protocol=cPickle.HIGHEST_PROTOCOL)
f.close()

Ensuite:

f = file(filename, 'rb')
loaded_objects = []
for i in range(3):
    loaded_objects.append(cPickle.load(f))
f.close()

Vous pouvez enregistrer vos dictionnaires dans un ordre spécifique afin que lors de leur chargement, vous ayez la possibilité de sélectionner uniquement les dictionnaires préférés.

Par exemple, si vous stockez les dictionnaires dans l'ordre: smallDict1, smallDict2, largeDict1
Vous ne pouvez charger que les plus petits en définissant la plage appropriée lors du chargement
(Ici for i in range(2) ...)

3
Tejas Shah