Modul pickle je jedním z prostředků vyhrazených pro perzistentní ukládání pythoních dat. To znamená, že data jím uložená mohou být např. k dispozici mezi dvěma časově vzdálenými běhy programu (a to i jiného).
Umí zaserializovat (téměř libovolnou) pythonovskou strukturu pomocí příslušného pickle-protokolu a uložit ji jako binární objekt buď do proměnné nebo do souboru. A samozřejmě ji pak zase umí z proměnné/souboru načíst a rozserializovat zpátky do příslušné struktury.
Pickle-protokolu jsou dnes již čtyři verze:
Pokud výslovně neřeknete jinak, používá se jako výchozí hodnota příslušející vaší verzi Python'u, takže pro Python 3.x je to verze protokolu 3.
Modul pickle
umí piklit a rozpiklovávat v zásadě do/z dvou různých míst – paměti nebo proudu (streamu):
po = pickle.dumps(o)
– zapiklí objekt o do proměnné po typu bytes()
o = pickle.loads(po)
– rozpiklí bajt-objekt po do datové struktury o
pickle.dump(o, file)
– zapiklí objekt o do binárního souboru file
o = pickle.load(file)
– rozpiklí do objektu o zapiklenou strukturu v binárním souboru file
file = open('soubor', 'rwb')
, nikoli cesta k souboru.
Zkusme zapiklit jednoduchý slovník, který obsahuje pouze data:
A teď si ho zase rozpikleme:
Vidíme, že na načtené datové struktuře jsou normálně k dispozici všechny její atributy.
Zaserializovat je možné následující typy:
None
, True
, False
__dict__
a __setstate__()
jsou piklitelné
Přitom:
Když náš datový slovník doplníme o odkaz na funkci (tedy referenci), zapiklí se pouze tento odkaz..
..což znamená, že při odpiklovávání musí příslušná funkce existovat (i když bude dělat něco úplně jiného):
Druhou možností by bylo zapiklit funkci jako řetězec a při rozpiklování ji převést na funkční tvar pomocí eval(), ale...
Piklící formát není nijak zabezpečen proti nebezpečným datům =>
Odpiklená data jsou totiž převedena do bajtkódu a vzápětí vykonána (aby mohly být příslušné datové a programové struktury k dispozici), je tudíž velkým bezpečnostním rizikem bezhlavě odpiklovávat všechno, co se vám dostane pod ruku!
Musíte-li pracovat s (nejen cizími) zapiklenými daty, mohou se vám hodit následujícíc dvě věci:
pickletools
(viz následující slajd) umožňují prozkoumat „vnitřnosti“ zapiklených dat bez nebezpečí spouštění vytvořeného bajtkódu.
Modul pickletools toho umí více (mimo jiné optimalizovat zapiklená data), ale na tomto místě se o něm zmiňujeme především proto, že umožňuje prozkoumat „assembler“ piklicího protokolu zkoumaného souboru, aniž by při tom jako pickle.load()
(či loads()
) získaný pythoní bajtkód rovnou i vykonal.
Programátor tak dostává do ruky nástroj, který mu umožňuje prozkoumat zapiklená data tak říkajíc „offline“, aniž by si jimi případně kompromitoval vlastní systém.
V programátorském rozhraní modulu jsou k dispozici následující metody:
dis(pickle, out=None, memo=None, indentlevel=4, annotate=0)
– vrací symbolickou disasemblaci (do operačních kódů piklicího protokolu) vstupního pickle-souboru;
genops(pickle)
– vrací iterátor přes jednotlivé operační kódy vstupního pickle-souboru;
optimize(picklestring)
– vrací optimalizovanou verzi vstupního pickle-řetězce.
PUT
.
Od verze Python'u 3.2 umožňuje modul pickletools
i své přímé volání z příkazové řádky:
Dostupné přepínače jsou:
-a
, --annotate
-o
, --output=<file>
-l
, --indentlevel=<num>
-m
, --memo
-p
, --preamble=<preamble>
Pro zajímavost zkusme ještě zapiklit slovník z předchozích slajdů, ale tentokrát v nejstarším ASCII-protokolu 0
: