2009-03-30 18 views
9

Moduł pikle wydaje się używać znaków ucieczki napisów podczas pikowania; staje się to nieefektywne, np. na niezliczonych tablicach. Rozważ następujące wartości: 1133 znaki i 4249 znaków. Długość znaków wynosi 1133 znaki i 4249 znaków.bardziej efektywny sposób na zbieranie napisów

z.dumps() odsłania coś w rodzaju "\ x00 \ x00" (rzeczywiste zera w łańcuchu), ale pikle wydaje się używać funkcji repr() ciągu znaków, podając "'\ x00 \ x00'" (zera jest ascii zer).

czyli ("0" w z.dumps() == false) i ("0" w cPickle.dumps (z.dumps()) == true)

+0

Powinieneś dodać konkretne pytanie do swojego wpisu re. –

+0

Co chcesz serializować ciąg znaków w języku Python lub liczbę bajtów? – jfs

+1

powinien być len (cPickle.dumps (z)) – vartec

Odpowiedz

23

Spróbuj użyć nowszej wersji protokół pikle z parametrem protokołu do pickle.dumps(). Wartością domyślną jest 0 i jest to format tekstowy ASCII. Są one większe niż 1 (sugeruję używanie pickle.HIGHEST_PROTOCOL). Formaty protokołów 1 i 2 (oraz 3, ale dla py3k) są binarne i powinny być bardziej konserwatywne.

+0

[Python 3 domyślnie używa protokołu 3.] (https://docs.python.org/3/library/pickle.html#data-stream-format) –

8

Rozwiązanie:

import zlib, cPickle 

def zdumps(obj): 
    return zlib.compress(cPickle.dumps(obj,cPickle.HIGHEST_PROTOCOL),9) 

def zloads(zstr): 
    return cPickle.loads(zlib.decompress(zstr)) 

>>> len(zdumps(z)) 
128 
+0

Oto coś więcej na ten temat: http://tinyurl.com/3ymhaj5. Zasadniczo, jeśli serializujesz dysk, możesz po prostu zrobić gzip.open() zamiast otworzyć. –

+0

@ slack3r ten link nie działa. – kynan

+0

Kodek 'ascii' nie może kodować znaku u '\ xda' w pozycji 1: porządkowy nie w zakresie (128) –

1

Ulepszenie odpowiedzi vartec jest, że wydaje się nieco więcej pamięci efektywne (ponieważ nie zmusza wszystko na sznurku):

def pickle(fname, obj): 
    import cPickle, gzip 
    cPickle.dump(obj=obj, file=gzip.open(fname, "wb", compresslevel=3), protocol=2) 

def unpickle(fname): 
    import cPickle, gzip 
    return cPickle.load(gzip.open(fname, "rb")) 
+0

-1 (1) Nie koduj protokołów o twardym kodzie, używaj '-1' lub' HIGHEST_PROTOCOL' . (2) Późniejsza kompresja jest ADD-ON i nie ma znaczenia dla jego pytania. (3) Określenie 'compresslevel' podczas dekompresji jest bezcelowe; wszelkie takie informacje, które mogą być konieczne do dekompresji pliku, byłyby przechowywane w nagłówku skompresowanego pliku - w przeciwnym razie w jaki sposób można by było rozpakować plik, gdyby nie wiadomo, jaki poziom kompresji został użyty? –

+0

(1) Następnie kod py2 nie odczytuje obiektów py3. (2) nagłówek mówi "poprawa odpowiedzi varteca", która używała kompresji - myślę, że zużyła mniej pamięci, ale mogło to być fałszywe wrażenie ... (3) naprawione – gatoatigrado

3

z.dumps() jest już marynowane ciąg znaków, tzn. można go rozpakować za pomocą metody pickle.loads():

>>> z = numpy.zeros(1000, numpy.uint8) 
>>> s = z.dumps() 
>>> a = pickle.loads(s) 
>>> all(a == z) 
True