2015-05-05 11 views
8

Qual è il modo più veloce per salvare/caricare un elenco di grandi dimensioni in Python 2.7? Mi scuso se questo è già stato chiesto, non ho trovato risposta a questa domanda esatta quando ho cercato ...Qual è il modo più veloce per salvare/caricare un elenco di grandi dimensioni in Python 2.7?

In particolare, sto testando i metodi per simulare qualcosa, e ho bisogno di confrontare il risultato da ciascun metodo provo per una soluzione esatta. Ho uno script Python che produce un elenco di valori che rappresentano la soluzione esatta e non voglio ricalcolarlo ogni volta che eseguo una nuova simulazione. Quindi, voglio salvarlo da qualche parte e caricare la soluzione invece di ricalcolarlo ogni volta che voglio vedere quanto sono buoni i risultati della mia simulazione.

Inoltre, non è necessario che il file salvato sia leggibile. Devo solo essere in grado di caricarlo in Python.

+1

puoi metterlo in salamoia https://docs.python.org/2/library/pickle.html, numpy.dump o http://docs.scipy.org/doc/numpy/reference/generated/numpy.save .html se vuoi usare array numpy –

+0

@PadraicCunningham Hmm, ok grazie! Sai se qualcuno di questi metodi è notevolmente più veloce dell'altro? Mi chiedo anche se accelererebbe o rallenterebbe il codice se lo modifico per produrre la soluzione di riferimento in formato array numerico anziché in un formato elenco. – nukeguy

+0

Se sei preoccupato per le prestazioni forse dovresti usare numpy per fare tutto il tuo lavoro –

risposta

7

Utilizzando np.load e ToList è significativamente più veloce rispetto a qualsiasi altra soluzione:

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 è molto più efficiente se si utilizza una matrice NumPy:

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 

Se si desidera una lista è ancora più veloce per chiamare tolist e usare np.carico:

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

Si tratta di 'pickle' o' cPickle'? – Scironic

+1

sembra relativamente in linea con questo: http://stackoverflow.com/questions/16833124/pickle-faster-than-cpickle-with-numeric-data Se questo è il caso, probabilmente suggerirei che OP va con Numpy se loro ' stanno già lavorando con Numpy e cPickle se non lo sono. - Ma sembra davvero una preferenza personale. – Scironic

0

Si consiglia di dare un'occhiata a Python serializzazione degli oggetti, pickle e cPickle http://pymotw.com/2/pickle/

pickle.dumps(obj[, protocol]) Se il parametro di protocollo viene omesso, il protocollo viene utilizzato 0. Se il protocollo viene specificato come valore negativo o HIGHEST_PROTOCOL, verrà utilizzata la versione del protocollo più elevata.

2

Come ha menzionato PadraicCunningham, è possibile mettere sott'occhio l'elenco.

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) 

carica la lista in un file.

E per estrarlo:

import pickle 

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

Il bit HIGHEST_PROTOCOL è facoltativo, ma è normalmente raccomandata. I protocolli definiscono il modo in cui serializzare l'oggetto con pickle, con protocolli inferiori che tendono a essere compatibili con le versioni precedenti di Python.

Vale la pena notare due cose:

C'è anche il modulo cPickle - scritti in C per ottimizzare la velocità. Lo usi come sopra.

Pickle è anche noto per avere alcune insicurezze (ci sono modi per manipolare il modo in cui pickle deserializza un oggetto, che puoi manipolare facendo fare a Python più o meno quello che vuoi). Di conseguenza, questa libreria non dovrebbe essere utilizzata quando aprirà dati sconosciuti. In casi estremi è possibile provare una versione più sicura come spickle: https://github.com/ershov/sPickle

Altre biblioteche mi consiglia la ricerca sono json e marshall.

+0

Grazie per la risposta. La parte di sicurezza non dovrebbe essere un problema per me dato che sarò l'unico ad avere accesso ai dati (a meno che il mio computer non venga hackerato o qualcosa del genere). Sai se cPickle è probabilmente la soluzione più veloce? – nukeguy

+1

Non posso dire quale sia la soluzione più veloce in quanto non ho eseguito i test. ma poichè 'cPickle' è scritto in' C', sarà molto più veloce della maggior parte delle cose scritte in 'Python' (la maggior parte delle librerie che usereste). Quindi direi che è una buona scommessa. – Scironic

+1

@nukeguy, vale anche la pena ricordare che non ci sono molti altri modi per archiviare oggetti 'Python' puri senza manipolarli in un formato utilizzabile, usando' pickle'/'cPickle' significa che non devi fare alcuna manipolazione o l'analisi e può solo salvare come è. Tutto ciò ovviamente influirà sul tempo di elaborazione. – Scironic

1

ho fatto un po 'di profilazione dei tanti metodi (ad eccezione del metodo di NumPy) e salamoia/cPickle è molto lenta su semplici insiemi di dati. Il modo più veloce dipende dal tipo di dati che stai salvando. Se stai salvando un elenco di stringhe e/o interi. Il modo più veloce che ho visto è quello di scriverlo direttamente su un file usando un ciclo for e ",". Join (...) rileggilo usando un ciclo for simile con .split (',').