概要

python で pickle.dump したクラス等の属性と振る舞いを持つようなオブジェクトが picke.load される時に、ロードされる側の環境に定義が無い場合や、定義内容が異なっている場合の挙動を確認する。

目次

プロジェクトの作成

作業用フォルダ作成

mkdir work_serialize
cd work_serialize

sample.py

class MyModule1(object):

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

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

serialize.py

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

import pickle


if __name__ == '__main__':
    with open("module1.dump", "rb") as f:
        module1 = pickle.load(f)
        module1.print()

シリアライズしてみる

python3 serialize.py

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

デシリアライズしてみる

そのまま実行すると問題なく実行できる

python3 deserialize.py
var1: AA

対象のモジュールがない場合

sample モジュールの名前を変えてからデシリアライズしてみると、以下の通りエラーになる。

mv sample.py sample_bak.py  # sample モジュールの名前を変更
python3 deserialize.py             # デシリアライズの実施

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

対象のオブジェクトの定義内容がシリアライズ時点から変更されている場合

sample.py を以下の通り変更する

class MyModule1(object):

    def __init__(self):
        pass

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

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

デシリアライズしてみると、変更後の定義内容で実行される。

python3 deserialize.py
var1: AA!!

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

python3 deserialize.py
var1 は AA

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


トップ   差分 バックアップ リロード   一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2020-01-12 (日) 02:49:22 (1738d)