【发布时间】:2022-10-04 18:28:16
【问题描述】:
dill 更新 dilled/undilled 对象本身的类定义,但不更新 dilled/undilled 对象包含的对象的类定义。
在任何一种情况下,pickle 都会更新类定义。
为什么莳萝不遵循与泡菜相同的行为?
泡菜
import os
import pickle
import tempfile
from dataclasses import dataclass, field
def pickle_save(x):
with tempfile.NamedTemporaryFile(delete=False) as f:
pickle.dump(x, f)
return f
def pickle_load(f):
with open(f.name, "rb") as f:
x = pickle.load(f)
os.unlink(f.name)
return x
@dataclass
class B:
attribute: str = "old"
def method_1(self):
print(f"old class: {self.attribute=}")
@dataclass
class A:
attribute_1: str = "old"
instances_of_B: list[B] = field(default_factory=list)
def method_1(self):
print(f"old class: {self.attribute_1=}, {self.instances_of_B=}")
def add_b_instance(self):
self.instances_of_B.append(B())
old_a = A()
old_a.add_b_instance()
old_a.method_1()
old_a.instances_of_B[0].method_1()
print(f"{old_a = }")
temp_file = pickle_save(old_a)
# old_a has been saved to file
# Next we update our class definitions
# then load old_a from file,
# and see whether the added methods exist
@dataclass
class A:
attribute_1: str = "new"
attribute_2: str = "new attribute 2"
instances_of_B: list[B] = field(default_factory=list)
def method_1(self):
print(f"new class: {self.attribute_1=}, {self.instances_of_B=}")
def method_2(self):
print("this method from A did not exist before")
print(f"this attribute did not exist before: {self.attribute_2=}")
@dataclass
class B:
attribute: str = "new"
def method_1(self):
print(f"new class: {self.attribute=}")
def method_2(self):
print("this method from B did not exist before")
new_a = pickle_load(temp_file)
print(f"{new_a=}")
new_a.method_1()
new_a.method_2()
new_a.instances_of_B[0].method_1()
new_a.instances_of_B[0].method_2()
腌制的 A 实例和包含的 B 实例的新方法_2 都可以在加载后使用:
old class: self.attribute_1='old', self.instances_of_B=[B(attribute='old')]
old class: self.attribute='old'
old_a = A(attribute_1='old', instances_of_B=[B(attribute='old')])
new_a=A(attribute_1='old', attribute_2='new attribute 2', instances_of_B=[B(attribute='old')])
new class: self.attribute_1='old', self.instances_of_B=[B(attribute='old')]
this method from A did not exist before
this attribute did not exist before: self.attribute_2='new attribute 2'
new class: self.attribute='old'
this method from B did not exist before
莳萝
import dill as pickle
只有腌制的A实例的新方法_2可以在加载后使用,而包含的B实例的新方法_2不能:
old class: self.attribute_1='old', self.instances_of_B=[B(attribute='old')]
old class: self.attribute='old'
old_a = A(attribute_1='old', instances_of_B=[B(attribute='old')])
new_a=A(attribute_1='old', attribute_2='new attribute 2', instances_of_B=[B(attribute='old')])
new class: self.attribute_1='old', self.instances_of_B=[B(attribute='old')]
this method from A did not exist before
this attribute did not exist before: self.attribute_2='new attribute 2'
old class: self.attribute='old'
Traceback (most recent call last):
File "c:\question_dill_pickle.py", line 78, in <module>
new_a.instances_of_B[0].method_2()
AttributeError: 'B' object has no attribute 'method_2'
【问题讨论】: