如何阻止Python中属性被序列化

23 投票
3 回答
10675 浏览
提问于 2025-04-15 23:42

我正在使用gnosis.xml.pickle这个工具,把我自己定义的一个类的对象转换成xml格式。这个对象是这样初始化的:

self.logger = MyLogger()

但是当我试图把这个对象保存成字符串时,出现了一个错误,提示说这个工具遇到了一个无法被转换的类型(thread.lock)。

有没有办法给logger这个属性加个标记,让这个工具知道不要尝试去转换这个属性呢?

3 个回答

3

你的类可以实现一个特殊的方法 __getstate__,这个方法可以返回实例中你想要被保存的部分。

这个方法还有几种不同的变体(不过 __getstate__ 和它的可选搭档方法 __setstate__ 是最常用的)——你可以查看网上的 Python 文档页面,关于 pickle 的部分,我之前已经提到过,因为它正好是记录 __getstate__ 的地方。

11

这可能是一个更好的解决方案,因为它允许通过 copy.deepcopy 创建的对象仍然拥有 self.logger

def __getstate__(self):
    d = self.__dict__.copy()
    if 'logger' in d:
        d['logger'] = d['logger'].name
    return d

def __setstate__(self, d):
    if 'logger' in d:
        d['logger'] = logging.getLogger(d['logger'])
    self.__dict__.update(d)
40

你可以在你的类里定义两个方法,__getstate____setstate__,这样就可以改变默认的序列化行为。

http://docs.python.org/library/pickle.html#object.__getstate__

__getstate__ 方法应该返回一个字典,这个字典包含你想要序列化的属性。

def __getstate__(self):
    d = dict(self.__dict__)
    del d['logger']
    return d

__setstate__ 方法则应该用提供的字典来设置你的对象。

def __setstate__(self, d):
    self.__dict__.update(d) # I *think* this is a safe way to do it

需要注意的是,在反序列化的时候,__init__ 方法不会被调用,所以你需要在 __setstate__ 方法里创建你的日志记录器。

撰写回答