Comment enregistrer et restaurer plusieurs variables en python?

106

J'ai besoin d'enregistrer une douzaine d'objets dans un fichier, puis de les restaurer plus tard. J'ai essayé d'utiliser une boucle for avec cornichon et étagère, mais cela n'a pas fonctionné correctement.

Éditer.
Tous les objets que j'essayais de sauvegarder étaient dans la même classe (j'aurais dû le mentionner avant), et je ne savais pas que je pouvais simplement sauvegarder toute la classe comme ceci:

import pickle
def saveLoad(opt):
    global calc
    if opt == "save":
        f = file(filename, 'wb')
        pickle.dump(calc, f, 2)
        f.close
        print 'data saved'
    elif opt == "load":
        f = file(filename, 'rb')
        calc = pickle.load(f)
    else:
        print 'Invalid saveLoad option'
lunarfyre
la source
1
Vous dites que vous avez essayé une boucle for. Veuillez poster ce code, et pourquoi «cela n'a pas fonctionné correctement» (c'est-à-dire ce qui s'est passé et ce que vous vouliez qu'il se passe).
Blair
Si vous êtes sous Windows, assurez-vous d'ouvrir les fichiers en mode binaire
John La Rooy
@gnibbler: le mode binaire n'est nécessaire que pour les protocoles autres que ceux par défaut ( docs.python.org/library/pickle.html#usage ).
Eric O Lebigot le

Réponses:

172

Si vous avez besoin de sauvegarder plusieurs objets, vous pouvez simplement les mettre dans une seule liste, ou tuple, par exemple:

import pickle

# obj0, obj1, obj2 are created here...

# Saving the objects:
with open('objs.pkl', 'w') as f:  # Python 3: open(..., 'wb')
    pickle.dump([obj0, obj1, obj2], f)

# Getting back the objects:
with open('objs.pkl') as f:  # Python 3: open(..., 'rb')
    obj0, obj1, obj2 = pickle.load(f)

Si vous avez beaucoup de données, vous pouvez réduire la taille du fichier en passant protocol=-1à dump(); pickleutilisera alors le meilleur protocole disponible au lieu du protocole historique par défaut (et plus rétrocompatible). Dans ce cas, le fichier doit être ouvert en mode binaire ( wbet rb, respectivement).

Le mode binaire doit également être utilisé avec Python 3, car son protocole par défaut produit des données binaires (c'est-à-dire non textuelles) (mode d'écriture 'wb'et mode de lecture 'rb').

Eric O Lebigot
la source
12
En Python 3.5, j'ai dû ouvrir le fichier en mode "octet", par exemple with open('objs.pickle', 'wb') as f:(notez le wb).
kbrose
Salut @Eric, à quoi faut-il with open('objs.pkl') as f:comparer simplement obj1, obj2 = pickle.load(open("objs.pkl","rb"))? Y a-t-il une différence entre ces deux?
balandongiv le
Avec le deuxième formulaire, vous ne fermez pas le fichier. Cela n'est pas considéré comme une bonne pratique, car le nombre de fichiers que vous pouvez ouvrir en parallèle est généralement assez limité par les systèmes d'exploitation (essayez une boucle qui ouvre les fichiers sans les fermer!). Cela dit, dans la pratique, ne pas fermer le fichier fonctionne souvent lorsque vous n'ouvrez pas beaucoup de fichiers.
Eric O Lebigot le
51

Il existe une bibliothèque intégrée appelée pickle. En utilisant, picklevous pouvez vider des objets dans un fichier et les charger plus tard.

import pickle

f = open('store.pckl', 'wb')
pickle.dump(obj, f)
f.close()

f = open('store.pckl', 'rb')
obj = pickle.load(f)
f.close()
Yossi
la source
1
I Python 3.4 utilise: f = open('store.pckl', 'wb')pour ouvrir un fichier dans lequel écrire. Reportez-vous à stackoverflow.com/questions/13906623/ ... Et utilisez `f = open ('store.pckl', 'rb') pour ouvrir un fichier à lire. Reportez-vous à stackoverflow.com/questions/7031699/… .
user3731622
est-ce spécifique à 3.4+? J'ai presque voté contre la réponse car elle génère des erreurs lorsque vous n'utilisez pas «b».
Wilmer E. Henao
12

Vous devriez regarder les modules d' étagères et de cornichons . Si vous avez besoin de stocker beaucoup de données, il peut être préférable d'utiliser une base de données

John La Rooy
la source
Je souhaite enregistrer un seul objet qui se connecte à un serveur cloud, afin de gérer si je me connecte plusieurs fois dans le temps, le serveur rejette ma demande. Le dumping d'un objet dans un fichier à l'aide du module pickle peut-il avoir un problème de sécurité? , par exemple où si quelqu'un obtient mon objet vidé, il peut se connecter à mon stockage en nuage sans utiliser de mot de passe.
alper
5

Une autre approche pour enregistrer plusieurs variables dans un fichier pickle est:

import pickle

a = 3; b = [11,223,435];
pickle.dump([a,b], open("trial.p", "wb"))

c,d = pickle.load(open("trial.p","rb"))

print(c,d) ## To verify
Guruprasad Raghavan
la source
4

Vous pouvez utiliser klepto, qui fournit une mise en cache persistante à la mémoire, au disque ou à la base de données.

dude@hilbert>$ python
Python 2.7.6 (default, Nov 12 2013, 13:26:39) 
[GCC 4.2.1 Compatible Apple Clang 4.1 ((tags/Apple/clang-421.11.66))] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from klepto.archives import file_archive
>>> db = file_archive('foo.txt')
>>> db['1'] = 1
>>> db['max'] = max
>>> squared = lambda x: x**2
>>> db['squared'] = squared
>>> def add(x,y):
...   return x+y
... 
>>> db['add'] = add
>>> class Foo(object):
...   y = 1
...   def bar(self, x):
...     return self.y + x
... 
>>> db['Foo'] = Foo
>>> f = Foo()
>>> db['f'] = f  
>>> db.dump()
>>> 

Ensuite, après le redémarrage de l'interpréteur ...

dude@hilbert>$ python
Python 2.7.6 (default, Nov 12 2013, 13:26:39) 
[GCC 4.2.1 Compatible Apple Clang 4.1 ((tags/Apple/clang-421.11.66))] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from klepto.archives import file_archive
>>> db = file_archive('foo.txt')
>>> db
file_archive('foo.txt', {}, cached=True)
>>> db.load()
>>> db
file_archive('foo.txt', {'1': 1, 'add': <function add at 0x10610a0c8>, 'f': <__main__.Foo object at 0x10510ced0>, 'max': <built-in function max>, 'Foo': <class '__main__.Foo'>, 'squared': <function <lambda> at 0x10610a1b8>}, cached=True)
>>> db['add'](2,3)
5
>>> db['squared'](3)
9
>>> db['f'].bar(4)
5
>>> 

Obtenez le code ici: https://github.com/uqfoundation

Mike McKerns
la source
7
L'OP n'a pas demandé de intégré.
Mike McKerns
4

L'approche suivante semble simple et peut être utilisée avec des variables de taille différente:

import hickle as hkl
# write variables to filename [a,b,c can be of any size]
hkl.dump([a,b,c], filename)

# load variables from filename
a,b,c = hkl.load(filename)
diable dans les détails
la source
hicklepackage est plus robuste (moins sujet aux erreurs) et encore plus simple (moins de code) que pickle.
user2340939