python - pathlib.Path 的子类对象在 pickle.load 后丢失自定义属性

标签 python python-3.x inheritance serialization pickle

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/

相关文章:

ios - 覆盖 UIScrollView 子类中的委托(delegate)属性

python - 包含同名类的 Python 模块在导入时如何工作?

Python Cron Job 与 Schedule 不工作

python - 在 Linux 上将 PIL 图像转换为视频

Python:如何获取过期的 SSL 证书日期?

c++ - 虚拟公共(public)继承?需要帮助理解代码

python - 如何在 cython 的结构中使用文件指针

Python 将日期时间转换为时间

python - 使用 for 循环生成列表

delphi - Delphi中如何指定调用哪个基类的重写方法?