2012-10-11 13 views
6

Mam marynowane obiekt w pliku o nazwie b1.pkl:Dlaczego ładowanie i zrzuty Pythona zwiększają rozmiar obiektu na dysku?

$ ls -l b* 
-rw-r--r-- 1 fireball staff 64743950 Oct 11 15:32 b1.pkl 

Potem uruchom następujący kod Pythona, aby załadować obiekt i zrzucić go do nowego pliku:

import numpy as np 
import cPickle as pkl 

fin = open('b1.pkl', 'r') 
fout = open('b2.pkl', 'w') 

x = pkl.load(fin) 
pkl.dump(x, fout) 

fin.close() 
fout.close() 

plików Kod ten tworzy się więcej niż dwa razy większy:

$ ls -l b* 
-rw-r--r-- 1 fireball staff 64743950 Oct 11 15:32 b1.pkl 
-rw-r--r-- 1 fireball staff 191763914 Oct 11 15:47 b2.pkl 

Czy ktoś może wyjaśnić dlaczego nowy plik jest więc znacznie większy niż oryginalny? Powinien zawierać dokładnie taką samą strukturę.

+3

była oryginalna marynowana z wykorzystaniem tego samego protokołu? – root

Odpowiedz

10

Możliwe, że oryginalny pikle użył jakiegoś innego protokołu. Na przykład spróbuj podać protocol=2 jako argument słowa kluczowego do drugiego pickle.dump i przetestuj go ponownie. Ogorek binarny powinien być znacznie mniejszy.

+0

Próbowałem określając protocol = 2 i, presto, wynikowy plik jest tego samego rozmiaru co oryginał! – user1389890

+0

to dobrze :) – root

3

pkl.dump (x, fout, 2) prawdopodobnie spowoduje ten sam rozmiar pliku. Brak określenia wersji protokołu sprawi, że marynarka użyje starej wersji 0.

4

Najprawdopodobniej oryginał b1.pkl został marynowane z użyciem bardziej wydajnego trybu protokołu (1 lub 2). Więc twój plik zaczyna się mniejszy.

Po załadowaniu cPickle automatycznie wykryje protokół z pliku. Ale kiedy przejdziesz i zrzucisz go ponownie z domyślnymi argumentami, użyje protokołu 0, który jest znacznie większy. Czyni to dla przenośności/kompatybilności. Musisz jawnie zażądać protokołu binarnego.

import numpy as np 
import cPickle 

# random data 
s = {} 
for i in xrange(5000): 
    s[i] = np.random.randn(5,5) 

# pickle it out the first time with binary protocol 
with open('data.pkl', 'wb') as f: 
    cPickle.dump(s, f, 2) 

# read it back in and pickle it out with default args 
with open('data.pkl', 'rb') as f: 
    with open('data2.pkl', 'wb') as o: 
     s = cPickle.load(f) 
     cPickle.dump(s, o) 

$ ls -l 
1174109 Oct 11 16:05 data.pkl 
3243157 Oct 11 16:08 data2.pkl 
+0

Kiedy wyrzuciłem oryginał, użyłem parametru pikle -1. Najwyraźniej spowodowało to bardziej kompaktową reprezentację na dysku. Przypuszczam, że to spowodowało, że pyton używał protokołu = 2. – user1389890

Powiązane problemy