#mynavi(python覚え書き)
#setlinebreak(on)

* 概要 [#zb723e1f]
#html(<div class="pl10">)
python で pickle.dump したクラス等の属性と振る舞いを持つようなオブジェクトが picke.load される時に、ロードされる側の環境に定義が無い場合や、定義内容が異なっている場合の挙動を確認する。
#html(</div>)

* 目次 [#hb91d93d]
#contents
- 関連
-- [[Python覚え書き]]
-- [[Javaでシリアライズとデシリアライズ]]

* プロジェクトの作成 [#s940d335]
#html(<div class="pl10">)

作業用フォルダ作成
#myterm2(){{
mkdir work_serialize
cd work_serialize
}}

sample.py
#mycode2(){{
class MyModule1(object):

    def __init__(self):
        self.var1 = "A" 

    def print(self):
        print(f'var1: {self.var1}')
}}

serialize.py
#mycode(){{
import pickle
import sample


if __name__ == '__main__':
    module1 = sample.MyModule1()
    module1.var1 = "AA"
    module1.var2 = "BB"
    with open("module1.dump", "wb") as f:
        pickle.dump(module1, f)
}}

deserialize.py
#mycode2(){{
import pickle


if __name__ == '__main__':
    with open("module1.dump", "rb") as f:
        module1 = pickle.load(f)
        module1.print()
}}
#html(</div>)

* シリアライズしてみる [#r57d4329]
#html(<div class="pl10">)
#myterm2(){{
python3 serialize.py

# シリアライズされたか確認
ls -1
__pycache__
deserialize.py
module1.dump    # シリアライズされたファイルが出来ている
sample.py
serialize.py
}}

#html(</div>)

* デシリアライズしてみる [#ea1e96de]
#html(<div class="pl10">)

そのまま実行すると問題なく実行できる
#myterm2(){{
python3 deserialize.py
var1: AA
}}

* 対象のモジュールがない場合 [#ffa99131]
#html(<div class="pl10">)

sample モジュールの名前を変えてからデシリアライズしてみると、以下の通りエラーになる。
#myterm2(){{
mv sample.py sample_bak.py  # sample モジュールの名前を変更
python3 deserialize.py             # デシリアライズの実施

Traceback (most recent call last):
  File "deserialize.py", line 6, in <module>
    module1 = pickle.load(f)
ModuleNotFoundError: No module named 'sample'
}}

#html(</div>)

* 対象のオブジェクトの定義内容がシリアライズ時点から変更されている場合 [#c20b0af1]
#html(<div class="pl10">)

sample.py を以下の通り変更する
#mycode2(){{
class MyModule1(object):

    def __init__(self):
        pass

    def print(self):
        print(f'var1 is {self.var1}!!')        # 内容を変更

    def display(self):
        print(f'var1 は {self.var1}')       # メソッドを追加
}}

デシリアライズしてみると、変更後の定義内容で実行される。
#myterm2(){{
python3 deserialize.py
var1: AA!!
}}

ちなみに追加したメソッド(display)も使用する事ができる。
deserialize.py の 「module1.print()」の部分を 「module1.display()」に変更して実行してみると以下の通り出力される。

#myterm2(){{
python3 deserialize.py
var1 は AA
}}

どうもメソッド定義まではシリアライズされない模様。
Java とかってどうだったっけ? と思ったので、Javaでもやってみたが同じ挙動だった。→ [[Javaでシリアライズとデシリアライズ]]

#html(</div>)


トップ   差分 バックアップ リロード   一覧 単語検索 最終更新   ヘルプ   最終更新のRSS