Serializacja Pythona - dlaczego marynowanie?

87

Zrozumiałem, że wytrawianie w Pythonie to sposób na „przechowywanie” obiektu w języku Python w sposób zgodny z programowaniem obiektowym - inny niż dane wyjściowe zapisane w pliku txt lub DB.

Czy masz więcej szczegółów lub odniesień w następujących kwestiach:

  • gdzie są „przechowywane” marynowane przedmioty?
  • dlaczego wytrawianie zachowuje reprezentację obiektów bardziej niż, powiedzmy, przechowywanie w DB?
  • czy mogę pobrać marynowane obiekty z jednej sesji powłoki Pythona do drugiej?
  • czy masz znaczące przykłady, kiedy serializacja jest przydatna?
  • czy serializacja z pikle oznacza „kompresję” danych?

Innymi słowy, szukam dokumentacji na temat marynowania - Python.doc wyjaśnia, jak zaimplementować marynatę, ale nie wydaje mi się, aby zagłębiać się w szczegóły dotyczące użycia i konieczności serializacji.

kiriloff
źródło
Zgaduję, czy zapisać stan do późniejszego przywrócenia lub udostępnić / skopiować obiekt do innego środowiska uruchomieniowego Pythona.
synthesizerpatel
13
Odpowiedzi na wiele pytań można znaleźć w artykule Wikipedii na temat serializacji: en.wikipedia.org/wiki/Serialization
NPE
5
pytasz, dlaczego potrzebuję Pickle do serializacji w Pythonie? czy raczej czym jest (celem) serializacja w końcu? .
moooeeeep
Może warto wspomnieć o problemach z bezpieczeństwem marynaty. Przykłady można znaleźć w dokumentacji oraz w wielu pytaniach SO, takich jak to .
djvg

Odpowiedzi:

99

Pickling to sposób na konwersję obiektu Pythona (listy, dyktowania itp.) Na strumień znaków. Chodzi o to, że ten strumień znaków zawiera wszystkie informacje niezbędne do zrekonstruowania obiektu w innym skrypcie Pythona.

Jeśli chodzi o miejsce przechowywania marynowanych informacji, zwykle można to zrobić:

with open('filename', 'wb') as f:
    var = {1 : 'a' , 2 : 'b'}
    pickle.dump(var, f)

To przechowywałoby marynowaną wersję naszego vardyktu w pliku „nazwa pliku”. Następnie w innym skrypcie można by załadować z tego pliku do zmiennej i odtworzyć słownik:

with open('filename','rb') as f:
    var = pickle.load(f)

Innym zastosowaniem do wytrawiania jest przesyłanie tego słownika przez sieć (być może za pomocą gniazd lub coś w tym rodzaju). Najpierw musisz przekonwertować go na strumień znaków, a następnie wysłać go przez połączenie z gniazdem.

Nie ma tu też żadnej „kompresji”… jest to po prostu sposób na konwersję z jednej reprezentacji (w pamięci RAM) do innej (w „tekście”).

About.com ma ładny wprowadzenie trawieniu tutaj .

austin1howard
źródło
2
zwykle with open('filename') as f: ...
bywało
3
Ponadto musiałbyś to zrobić with open(filename, 'wb') as f: ...lub nie byłbyś w stanie pisać do pliku.
Tim Pietzcker
Dzięki!! Ten dotyczący zarządzania trwałością w Pythonie jest fajny, tutaj
kiriloff
1
Ogólnie rzecz biorąc, nie jest dobrym pomysłem używanie picklesłownika do przesyłania słownika przez sieć (tutaj json może być lepszy). Chociaż w rzadkich przypadkach może się przydać np multiprocessing. Module.
jfs
@Tim Pietzcker: protocol=0(domyślnie w Python2.x) może być używany z plikami otwieranymi w trybie tekstowym.
jfs
36

W obliczeniach rozproszonych i równoległych konieczne jest wytrawianie.

Załóżmy, że chcesz wykonać równoległą redukcję mapy z multiprocessing(lub między węzłami klastra za pomocą pyina ), a następnie musisz upewnić się, że funkcja, którą chcesz zmapować w równoległych zasobach, zostanie zniszczona. Jeśli się nie wytrawia, nie możesz wysłać go do innych zasobów w innym procesie, komputerze itp. Zobacz także tutaj dobry przykład.

Aby to zrobić, używam koperku , który może serializować prawie wszystko w Pythonie. Dill ma również dobre narzędzia, które pomogą Ci zrozumieć, co powoduje niepowodzenie wytrawiania w przypadku awarii kodu.

I tak, ludzie używają wybierania, aby zapisać stan obliczeń, sesję ipython lub cokolwiek innego. Możesz także rozszerzyć pickle's Pickler i UnPickler, aby wykonać kompresję z bz2lub, gzipjeśli chcesz.

Mike McKerns
źródło
0

Uważam, że jest to szczególnie przydatne w przypadku dużych i złożonych klas niestandardowych. W konkretnym przykładzie, o którym myślę, „Zbieranie” informacji (z bazy danych) w celu utworzenia klasy to już połowa sukcesu. Następnie informacje przechowywane w klasie mogą zostać zmienione przez użytkownika w czasie wykonywania.

Możesz mieć inną grupę tabel w bazie danych i napisać inną funkcję, która przejrzy wszystkie zapisane dane i zapisze je w nowych tabelach bazy danych. Następnie musiałbyś napisać inną funkcję, aby móc załadować coś zapisanego, wczytując wszystkie te informacje z powrotem.

Alternatywnie możesz wytrawić całą klasę bez zmian, a następnie zapisać ją w jednym polu w bazie danych. Następnie, gdy przejdziesz do ponownego załadowania, wszystko zostanie załadowane z powrotem, tak jak poprzednio. Może to w efekcie zaoszczędzić dużo czasu i kodu podczas zapisywania i pobierania skomplikowanych klas.

Kurczak Max
źródło
-1

jest to rodzaj serializacji. użyj cPickle, jest znacznie szybszy niż marynowanie.

import pickle
##make Pickle File
with open('pickles/corups.pickle', 'wb') as handle:
    pickle.dump(corpus, handle)

#read pickle file
with open('pickles/corups.pickle', 'rb') as handle:
    corpus = pickle.load(handle)
Paritosh Yadav
źródło