2015-05-05 18 views
8

Was ist der schnellste Weg, eine große Liste in Python 2.7 zu speichern/zu laden? Ich entschuldige mich, wenn dies bereits gefragt wurde, konnte ich keine Antwort auf diese genaue Frage finden, als ich suchte ...Was ist der schnellste Weg, um eine große Liste in Python 2.7 zu speichern/zu laden?

Genauer gesagt, ich testen Methoden für die Simulation von etwas, und ich muss das Ergebnis vergleichen Von jeder Methode teste ich zu einer exakten Lösung aus. Ich habe ein Python-Skript, das eine Liste von Werten erzeugt, die die exakte Lösung darstellen, und ich möchte es nicht jedes Mal neu berechnen, wenn ich eine neue Simulation starte. Daher möchte ich es irgendwo speichern und einfach die Lösung laden, anstatt sie jedes Mal neu zu berechnen, wenn ich sehen möchte, wie gut meine Simulationsergebnisse sind.

Ich brauche auch nicht die gespeicherte Datei für Menschen lesbar. Ich muss es nur in Python laden können.

+1

können Sie es picken https://docs.python.org/2/library/pickle.html, numpy.dump oder http://docs.scipy.org/doc/numpy/reference/generated/numpy.save .html, wenn Sie numpy Arrays verwenden möchten –

+0

@PadraicCunningham Hmm, ok danke! Weißt du, ob eine dieser Methoden merklich schneller ist als die andere? Ich frage mich auch, ob es den Code beschleunigen oder verlangsamen würde, wenn ich ihn modifiziere, um die Referenzlösung in einem numply array-Format anstelle eines Listenformats zu erzeugen. – nukeguy

+0

Wenn Sie über die Leistung besorgt sind, sollten Sie vielleicht numpy verwenden, um alle Ihre Arbeit zu tun –

Antwort

7

np.load und ToList Verwendung ist deutlich schneller als jede andere Lösung:

In [77]: outfile = open("test.pkl","w") 
In [78]: l = list(range(1000000)) 

In [79]: timeit np.save("test",l) 
10 loops, best of 3: 122 ms per loop 

In [80]: timeit np.load("test.npy").tolist() 
10 loops, best of 3: 20.9 ms per loop 

In [81]: timeit pickle.load(outfile) 
1 loops, best of 3: 1.86 s per loop 

In [82]: outfile = open("test.pkl","r") 

In [83]: timeit pickle.load(outfile) 
1 loops, best of 3: 1.88 s per loop 

In [84]: cPickle.dump(l,outfile) 
....: 
1 loops, best of 3: 
273 ms per loop  
In [85]: outfile = open("test.pkl","r") 
In [72]: %%timeit 
cPickle.load(outfile) 
    ....: 
1 loops, best of 3: 
539 ms per loop 

In Python 3 numpy ist wesentlich effizienter, wenn Sie eine numpy Array verwenden:

In [24]: %%timeit     
out = open("test.pkl","wb") 
pickle.dump(l, out) 
    ....: 
10 loops, best of 3: 27.3 ms per loop 

In [25]: %%timeit 
out = open("test.pkl","rb") 
pickle.load(out) 
    ....: 
10 loops, best of 3: 52.2 ms per loop 

In [26]: timeit np.save("test",l) 
10 loops, best of 3: 115 ms per loop 

In [27]: timeit np.load("test.npy") 
100 loops, best of 3: 2.35 ms per loop 

Wenn Sie möchten, In einer Liste ist es wieder schneller, tolist anzurufen und np zu verwenden.Last:

In [29]: timeit np.load("test.npy").tolist() 
10 loops, best of 3: 37 ms per loop 
+1

Ist das mit 'Pickle' oder' cPickle'? – Scironic

+1

scheint relativ inline mit diesem: http://stackoverflow.com/questions/16833124/pickle-faster-than-cpickle-with-numeric-data Wenn das der Fall ist, würde ich wahrscheinlich vorschlagen, dass OP geht mit numpy, wenn sie ' re arbeiten bereits mit numpy, und cPickle, wenn sie nicht sind. - Aber es scheint wirklich persönliche Vorliebe zu sein. – Scironic

0

Sie möchten vielleicht einen Blick auf Python Objektserialisierung nehmen, pickle und cPickle http://pymotw.com/2/pickle/

pickle.dumps(obj[, protocol]) Wenn das Protokoll Parameter weggelassen wird, Protokoll wird 0 verwendet. Wenn das Protokoll als negativer Wert oder HIGHEST_PROTOCOL angegeben wird, wird die höchste Protokollversion verwendet.

2

Wie PadraicCunningham erwähnt hat, können Sie die Liste einlegen.

import pickle 

lst = [1,2,3,4,5] 

with open('file.pkl', 'wb') as pickle_file: 
    pickle.dump(lst, pickle_file, protocol=pickle.HIGHEST_PROTOCOL) 

Dies lädt die Liste in eine Datei.

Und es zu extrahieren:

import pickle 

with open('file.pkl', 'rb') as pickle_load: 
    lst = pickle.load(pickle_load) 
print(lst) # prints [1,2,3,4,5] 

Das HIGHEST_PROTOCOL Bit ist optional, wird aber normalerweise empfohlen. Protokolle definieren, wie Pickle das Objekt serialisiert, wobei niedrigere Protokolle dazu tendieren, mit älteren Versionen von Python kompatibel zu sein.

Es ist erwähnenswert, zwei weitere Dinge:

Es gibt auch das cPickle Modul ist - in C geschrieben Geschwindigkeit zu optimieren. Sie verwenden dies auf die gleiche Weise wie oben.

Pickle ist auch dafür bekannt, einige Unsicherheiten zu haben (es gibt Möglichkeiten zu manipulieren, wie Essiggurke ein Objekt deserialisiert, das Sie manipulieren können, damit Python mehr oder weniger alles macht, was Sie wollen). Daher sollte diese Bibliothek nicht verwendet werden, wenn unbekannte Daten geöffnet werden. In extremen Fällen können Sie eine sicherere Version wie spickle ausprobieren: https://github.com/ershov/sPickle

Andere Bibliotheken, die ich empfehlen würde aufzublicken sind json und marshall.

+0

Danke für Ihre Antwort. Der Sicherheitsteil sollte für mich kein Problem sein, da ich der einzige sein werde, der Zugriff auf die Daten hat (außer mein Computer wird gehackt oder so). Weißt du, ob cPickle wahrscheinlich die schnellste Lösung ist? – nukeguy

+1

Ich kann nicht sagen, was die schnellste Lösung ist, da ich die Tests nicht ausgeführt habe. aber da 'cPickle' in' C' geschrieben wird, wird es viel schneller sein als die meisten Dinge, die in 'Python' geschrieben sind (Die meisten Bibliotheken, die Sie verwenden würden). Also würde ich sagen, es ist eine gute Wette. – Scironic

+1

@nukeguy, es ist auch erwähnenswert, dass es nicht viele andere Möglichkeiten gibt, reine 'Python'-Objekte zu speichern, ohne sie in ein praktikables Format zu manipulieren, wobei' pickle'/'cPickle' bedeutet, dass Sie keine Manipulation vornehmen müssen oder Parsing und kann nur speichern wie es ist. All dies wird natürlich in die Verarbeitungszeit einberechnet. – Scironic

1

Ich habe einige Profilierung von vielen Methoden durchgeführt (mit Ausnahme der numpy-Methode) und Gurke/cPickle ist sehr langsam auf einfachen Datensatz. Der schnellste Weg hängt davon ab, welche Art von Daten Sie speichern. Wenn Sie eine Liste von Strings und/oder Ganzzahlen speichern. Der schnellste Weg, den ich gesehen habe, ist es, ihn direkt in eine Datei zu schreiben, indem man eine for-Schleife und ',' verwendet. (...) lies ihn mit einer ähnlichen for-Schleife mit .split (',') wieder ein.

Verwandte Themen