Come faccio a salvare e ripristinare più variabili in Python?


105

Ho bisogno di salvare circa una dozzina di oggetti in un file e quindi ripristinarli in un secondo momento. Ho provato a usare un ciclo for con pickle e shelve ma non ha funzionato bene.

Modificare.
Tutti gli oggetti che stavo cercando di salvare erano nella stessa classe (avrei dovuto menzionarlo prima) e non mi rendevo conto che avrei potuto salvare l'intera classe in questo modo:

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'

1
Dici di aver provato un ciclo for. Per favore pubblica quel codice e spiega perché "non ha funzionato bene" (cioè cosa è successo e cosa volevi che accadesse).
Blair

Se sei su Windows, assicurati di aprire i file in modalità binaria
John La Rooy

@gnibbler: la modalità binaria è necessaria solo per i protocolli non predefiniti ( docs.python.org/library/pickle.html#usage ).
Eric O Lebigot

Risposte:


170

Se devi salvare più oggetti, puoi semplicemente metterli in un unico elenco, o tupla, ad esempio:

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)

Se hai molti dati, puoi ridurre la dimensione del file passando protocol=-1a dump(); pickleutilizzerà quindi il miglior protocollo disponibile invece del protocollo storico predefinito (e più compatibile con le versioni precedenti). In questo caso, il file deve essere aperto in modalità binaria ( wbe rb, rispettivamente).

La modalità binaria dovrebbe essere usata anche con Python 3, poiché il suo protocollo predefinito produce dati binari (cioè non di testo) (modalità di scrittura 'wb'e modalità di lettura 'rb').


12
In Python 3.5, ho dovuto aprire il file in modalità "byte", ad esempio with open('objs.pickle', 'wb') as f:(nota il wb).
kbrose

Ciao @Eric, qual è il bisogno di with open('objs.pkl') as f:confrontare semplicemente obj1, obj2 = pickle.load(open("objs.pkl","rb"))? C'è qualche differenza tra questi due?
balandongiv

Con il secondo modulo non si chiude il file. Questa non è considerata una buona pratica, poiché il numero di file che è possibile aprire in parallelo è solitamente abbastanza limitato dai sistemi operativi (prova un ciclo che apre i file senza chiuderli!). Detto questo, in pratica, non chiudere il file spesso funziona, quando non si aprono molti file.
Eric O Lebigot

51

C'è una libreria incorporata chiamata pickle. Usando picklepuoi scaricare gli oggetti in un file e caricarli in seguito.

import pickle

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

f = open('store.pckl', 'rb')
obj = pickle.load(f)
f.close()

1
Uso di Python 3.4: f = open('store.pckl', 'wb')per aprire un file su cui scrivere. Fare riferimento a stackoverflow.com/questions/13906623/… E utilizzare `f = open ('store.pckl', 'rb') per aprire un file da cui leggere. Fare riferimento a stackoverflow.com/questions/7031699/… .
user3731622

è specifico per 3.4+? Ho quasi votato contro la risposta perché genera errori quando non usi "b".
Wilmer E. Henao

12

Dovresti guardare i moduli scaffale e sottaceto . Se hai bisogno di memorizzare molti dati, potrebbe essere meglio usare un database


Voglio salvare un singolo oggetto che accede a un server cloud, in modo da gestire se accedo più volte nel tempo, il server rifiuta la mia richiesta. Il dumping di un oggetto in un file utilizzando il modulo pickle può avere problemi di sicurezza? , ad esempio se qualcuno ottiene il mio oggetto scaricato, può accedere al mio archivio cloud senza utilizzare una password.
alper

5

Un altro approccio per salvare più variabili in un file pickle è:

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

4

È possibile utilizzare klepto, che fornisce la memorizzazione nella cache persistente alla memoria, al disco o al database.

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

Quindi, dopo il riavvio dell'interprete ...

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

Ottieni il codice qui: https://github.com/uqfoundation


7
L'OP non ha chiesto il built-in.
Mike McKerns

4

Il seguente approccio sembra semplice e può essere utilizzato con variabili di dimensioni diverse:

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)

hicklepacchetto è più robusto (meno soggetto a errori) e persino più semplice (meno codice) di pickle.
user2340939
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.