Wie speichere und stelle ich mehrere Variablen in Python wieder her?

104

Ich muss ungefähr ein Dutzend Objekte in einer Datei speichern und sie später wiederherstellen. Ich habe versucht, eine for-Schleife mit Gurke und Regal zu verwenden, aber es hat nicht richtig funktioniert.

Bearbeiten.
Alle Objekte, die ich speichern wollte, befanden sich in derselben Klasse (ich hätte das schon früher erwähnen sollen), und ich wusste nicht, dass ich die gesamte Klasse einfach so speichern konnte:

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
quelle
1
Sie sagen, Sie haben eine for-Schleife ausprobiert. Bitte posten Sie diesen Code und warum "es nicht richtig funktioniert hat" (dh was passiert ist und was Sie passieren wollten).
Blair
Wenn Sie unter Windows sind, stellen Sie sicher, dass Sie die Dateien im Binärmodus öffnen
John La Rooy
@gnibbler: Der Binärmodus wird nur für die nicht standardmäßigen Protokolle benötigt ( docs.python.org/library/pickle.html#usage ).
Eric O Lebigot

Antworten:

170

Wenn Sie mehrere Objekte speichern müssen, können Sie sie einfach in eine einzelne Liste oder ein Tupel einfügen, zum Beispiel:

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)

Wenn Sie viele Daten haben, können Sie die Dateigröße reduzieren, indem Sie protocol=-1an übergeben dump(). pickleverwendet dann das beste verfügbare Protokoll anstelle des standardmäßigen historischen (und abwärtskompatibleren) Protokolls. In diesem Fall muss die Datei im Binär - Modus (geöffnet werden wbund rbjeweils).

Der Binärmodus sollte auch mit Python 3 verwendet werden, da sein Standardprotokoll Binärdaten (dh Nicht-Textdaten) erzeugt (Schreibmodus 'wb'und Lesemodus 'rb').

Eric O Lebigot
quelle
12
In Python 3.5 musste ich die Datei im "Byte" -Modus öffnen, z. B. with open('objs.pickle', 'wb') as f:(beachten Sie das wb).
Brose
Hallo @Eric, womit muss with open('objs.pkl') as f:man einfach vergleichen obj1, obj2 = pickle.load(open("objs.pkl","rb"))? Gibt es einen Unterschied zwischen diesen beiden?
Balandongiv
Mit dem zweiten Formular schließen Sie die Datei nicht. Dies wird nicht als bewährte Methode angesehen, da die Anzahl der Dateien, die Sie parallel öffnen können, normalerweise von den Betriebssystemen sehr begrenzt ist (versuchen Sie eine Schleife, die Dateien öffnet, ohne sie zu schließen!). In der Praxis funktioniert es jedoch häufig, die Datei nicht zu schließen, wenn Sie nicht viele Dateien öffnen.
Eric O Lebigot
49

Es gibt eine eingebaute Bibliothek namens pickle. Mit können pickleSie Objekte in eine Datei sichern und später laden.

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
quelle
1
Ich Python 3.4 benutze: f = open('store.pckl', 'wb')um eine Datei zu öffnen, in die geschrieben werden soll. Siehe stackoverflow.com/questions/13906623/… und verwenden Sie `f = open ('store.pckl', 'rb'), um eine Datei zum Lesen zu öffnen. Siehe stackoverflow.com/questions/7031699/… .
user3731622
ist das spezifisch für 3.4+? Ich habe die Antwort fast abgelehnt, weil sie Fehler erzeugt, wenn Sie nicht 'b' verwenden.
Wilmer E. Henao
12

Sie sollten sich die Regal- und Essiggurkenmodule ansehen . Wenn Sie viele Daten speichern müssen, ist es möglicherweise besser, eine Datenbank zu verwenden

John La Rooy
quelle
Ich möchte ein einzelnes Objekt speichern, das sich bei einem Cloud-Server anmeldet. Wenn ich mich im Laufe der Zeit mehrmals anmelde, lehnt der Server meine Anfrage ab. Kann das Ablegen eines Objekts in eine Datei mithilfe des Pickle-Moduls Sicherheitsprobleme verursachen? Zum Beispiel, wenn jemand mein ausgegebenes Objekt erhält, kann er sich ohne Verwendung eines Kennworts bei meinem Cloud-Speicher anmelden.
Alper
5

Ein anderer Ansatz zum Speichern mehrerer Variablen in einer Pickle-Datei ist:

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

Sie können verwenden klepto, um dauerhaftes Caching für Speicher, Festplatte oder Datenbank bereitzustellen.

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

Dann, nach dem Neustart des Interpreters ...

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

Den Code erhalten Sie hier: https://github.com/uqfoundation

Mike McKerns
quelle
7
Das OP hat nicht nach Einbauten gefragt.
Mike McKerns
3

Der folgende Ansatz scheint einfach zu sein und kann mit Variablen unterschiedlicher Größe verwendet werden:

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)
Teufel im Detail
quelle
hicklePaket ist robuster (weniger fehleranfällig) und noch einfacher (weniger Code) als pickle.
user2340939