内部类的序列化

2 投票
2 回答
2331 浏览
提问于 2025-04-16 14:28

我有一个叫做 model 的Python模块,里面大致包含以下内容:

class Database:

    class Publiation(object):
        pass

    class Article(Publication):
        pass

    class Book(Publication):
        pass

class AnotherDatabase:

    class Seminar(object):
        pass

    ...

我把数据库中的对象定义成类,并把这些类放在一个主类下面,这样可以更清晰地组织它们。这些对象是从一个很大的XML文件中解析出来的,这个过程需要一些时间。我想把导入的对象进行“打包”,这样下次加载的时候就能更快。

但是我遇到了一个错误:

pickle.PicklingError: Can't pickle : it's not found as project.model.Article

现在这个类是 project.model.Article,而不是之前定义的 project.model.Database.Article。我能解决这个错误,同时保持类的嵌套结构吗?把类嵌套在一起组织,这样做是个坏主意吗?

2 个回答

5

当我们创建一个内部类时,解释器并不知道这个类是在哪个外部类里面定义的,因为这个信息并没有被记录下来。这就是为什么在使用pickle的时候,它不知道去哪里找Article这个类。

由于这个原因,使用内部类会出现很多问题,不仅仅是在使用pickle的时候。如果在模块范围内有同名的类,就会造成很多混淆,因为没有简单的方法来区分这两种类型(比如在使用repr或者调试的时候)。

因此,通常情况下,除非你有非常好的理由,否则最好避免在Python中使用嵌套类。

2

把你的类保持在一个简单的结构里,确实会简单很多。你也可以用包来把这些类放在一起。

另外,还有一个叫做 cerealizer 的替代序列化工具,我觉得它可以处理嵌套的类。在反序列化之前,你需要先把这些类注册到这个工具里。我之前用过这个工具,当 pickle 不够用的时候(还有一些和类相关的问题),它的表现很好!

撰写回答