2015-05-05 12 views
8

Jaki jest najszybszy sposób na zapisanie/załadowanie dużej listy w Pythonie 2.7? Przepraszam, jeśli to zostało już zadane, nie mogłem znaleźć odpowiedzi na to dokładne pytanie, kiedy szukałem ...Jaki jest najszybszy sposób na zapisanie/załadowanie dużej listy w Pythonie 2.7?

Dokładniej, testuję metody symulacji czegoś i muszę porównać wynik z każdej metody testuję dokładne rozwiązanie. Mam skrypt Python, który tworzy listę wartości reprezentujących dokładne rozwiązanie i nie chcę go ponownie obliczać za każdym razem, gdy uruchomię nową symulację. Dlatego chcę go gdzieś zapisać i po prostu wczytać rozwiązanie zamiast go ponownie obliczać za każdym razem, gdy chcę zobaczyć, jak dobre są moje wyniki symulacji.

Nie potrzebuję również zapisanego pliku, aby można go było odczytać. Po prostu muszę go wczytać w Pythonie.

+1

możesz go pobrać https://docs.python.org/2/library/pickle.html, numpy.dump lub http://docs.scipy.org/doc/numpy/reference/generated/numpy.save .html jeśli chcesz użyć numpy tablice –

+0

@PadraicCunningham Hmm, ok dzięki! Czy wiesz, że któraś z tych metod jest zauważalnie szybsza od drugiej? Zastanawiam się też, czy przyspieszyłoby to lub spowolniło kod, jeśli zmodyfikuję go, aby wytworzyć rozwiązanie referencyjne w formacie tablicy liczbowej zamiast formatu listy. – nukeguy

+0

Jeśli martwisz się wydajnością, powinieneś używać numpy do wykonania całej pracy –

Odpowiedz

7

Korzystanie np.load i ToList jest znacznie szybciej niż jakiekolwiek inne rozwiązanie:

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 

W Pythonie 3 numpy jest znacznie bardziej efektywny, jeśli używasz numpy tablicy:

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 

Jeśli chcesz lista jest znowu szybsza, aby wywołać tolist i użyć np.obciążenie:

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

Czy jest to z 'pickle' lub' cPickle'? – Scironic

+1

wydaje się względnie zgodne z tym: http://stackoverflow.com/questions/16833124/pickle-faster-than-cpickle-with-numeric-data Jeśli tak jest, to prawdopodobnie sugerowałbym, że OP idzie z numpy, jeśli " ponownie pracują z numpy już i cPickle, jeśli nie są. - Ale to naprawdę wydaje się być osobistą preferencją. – Scironic

0

Możesz przyjrzeć Python serializacji obiektu, pickle i cPickle http://pymotw.com/2/pickle/

pickle.dumps(obj[, protocol]) Jeśli parametr protokół zostanie pominięty, używany jest protokół 0. Jeśli protokół zostanie określony jako wartość ujemna lub HIGHEST_PROTOCOL, zostanie użyta najwyższa wersja protokołu.

2

Jak wspomniał PadraicCunningham, możesz wybrać listę.

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) 

to ładuje listę do pliku.

I aby go rozpakować:

import pickle 

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

HIGHEST_PROTOCOL bit jest opcjonalne, ale jest zwykle zalecane. Protokoły definiują, w jaki sposób piksel będzie serializować obiekt, a niższe protokoły będą zwykle zgodne ze starszymi wersjami Pythona.

Warto zauważyć dwie rzeczy:

Istnieje również moduł cPickle - napisany w C, aby zoptymalizować szybkość. Używasz tego w taki sam sposób jak powyżej.

Ogórek jest również znany z pewnej niepewności (istnieją sposoby manipulowania sposobem deserializacji obiektu, który można zmanipulować, aby Python robił mniej więcej to, co chcesz). W rezultacie biblioteka ta nie powinna być używana, gdy będzie otwierać nieznane dane. W skrajnych przypadkach można wypróbować bezpieczniejszą wersję jak spickle: https://github.com/ershov/sPickle

Inne biblioteki polecam patrząc są json i marshall.

+0

Dzięki za odpowiedź. Część dotycząca bezpieczeństwa nie powinna być dla mnie problemem, ponieważ będę jedyną osobą mającą dostęp do danych (chyba że mój komputer zostanie zhakowany lub coś takiego). Czy wiesz, czy cPickle jest prawdopodobnie najszybszym rozwiązaniem? – nukeguy

+1

Nie mogę powiedzieć, jakie jest najszybsze rozwiązanie, ponieważ nie przeprowadziłem testów. ale ponieważ 'cPickle' jest napisany w' C', będzie o wiele szybszy niż większość rzeczy napisanych w 'Pythonie' (Większość bibliotek, których będziesz używał). Powiedziałbym, że to dobry zakład. – Scironic

+1

@nukeguy, warto również wspomnieć, że nie ma zbyt wielu innych sposobów na przechowywanie czystych obiektów 'Python' bez manipulowania nimi w nadającym się do użycia formacie, użycie' pickle'/'cPickle' oznacza, że ​​nie musisz wykonywać żadnych manipulacji lub parsowanie i można po prostu zapisać tak jak jest. Wszystko to oczywiście wpłynie na czas przetwarzania. – Scironic

1

Zrobiłem trochę profilowanie wielu metod (z wyjątkiem metody numpy) i słone/cPickle jest bardzo powolny na prostych zestawów danych. Najszybszy sposób zależy od rodzaju zapisywanych danych. Jeśli zapisujesz listę ciągów znaków i/lub liczb całkowitych. Najszybszym sposobem, jaki widziałem, jest napisanie go bezpośrednio do pliku za pomocą pętli for i "." Join (...) odczyta go za pomocą podobnej pętli for z .split (',').