from pathlib import Path
import pickle
class P(type(Path())):
def __init__(self, *args):
super().__init__()
self.a = ''
p = P()
p.a = 'x'
with open('xx', 'wb') as wf:
pickle.dump(p, wf)
p1 = pickle.load(open('xx', 'rb'))
print(p1.a) # here p1.a is ''
我正在创建 pathlib.Path
的子类,并希望向其添加一些自定义属性。
问题是自定义属性在 pickle 重新加载后会丢失。
如何解决这个问题。
我尝试过的其他解决方案:
- 使用
__slots__
,同样的问题。 - 使用组合而不是继承,然后通过实现 __getattr__ 来调度类似路径的方法。但是,在这种情况下,
self.path
未在pickle.load
内初始化,从而导致无休止地调用__getattr__
。
class File():
def __init__(self, *args):
self.path = Path(*args)
def __getattr__(self, item):
return getattr(self.path, item)
p = File('aaa')
p.exists() # no error
with open('xx', 'wb') as wf:
pickle.dump(p, wf)
p1 = pickle.load(open('xx', 'rb'))
# RecursionError: maximum recursion depth exceeded.
# This is due to call of self.path, in that moment, path is not in self.__dict__
最佳答案
一种方法是使用 copyreg
模块将 pickle 支持函数关联到类的实例,如下所示。请注意,我还必须修改您的 P
类处理参数的方式 - 它不再忽略它们。
import copyreg
from pathlib import Path
import pickle
class P(type(Path())):
def __init__(self, *args):
super().__init__()
self.a = args[0] if args else ''
def pickle_P(p):
print("pickling a P instance...")
return P, (p.a,)
copyreg.pickle(P, pickle_P)
p = P()
p.a = 'x'
q = P('y')
with open('xx', 'wb') as outp:
pickle.dump(p, outp)
pickle.dump(q, outp)
with open('xx', 'rb') as inp:
p1 = pickle.load(inp)
q1 = pickle.load(inp)
print('p1.a = {!r}'.format(p1.a))
print('q1.a = {!r}'.format(q1.a))
输出:
pickling a P instance...
pickling a P instance...
p1.a = 'x'
q1.a = 'y'
关于python - pathlib.Path 的子类对象在 pickle.load 后丢失自定义属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66685994/