Python中带有__getattr__方法的对象的pickle返回`TypeError,object not callable`

时间:2018-06-16 13:36:28

标签: python python-3.x pickle

我想定义一个类,使用None方法为未知属性返回__getattr__

这样做之后,我试图将该类的对象转储到Pickle。

然而,我收到了错误

Traceback (most recent call last):
  File "c:\SVN\Scripts\Rally\examples\t_pickle_None.py", line 14, in <module>
    pickle.dump(toto, f, pickle.HIGHEST_PROTOCOL)
TypeError: 'NoneType' object is not callable

没有定义__getattr__,它运行正常,但我想保留此功能。

以下是我的代码:如何使其与__getattr__一起使用?

由于

import pickle
from typing import Any

class Toto:
    def __init__(self, name:str) -> None:
        self.name = name

    def __getattr__(self, _: str) -> Any:
        """Return None for all unknown attributes"""
        return None

toto = Toto("Toto")
with open('toto.pkl', 'wb') as f:
    pickle.dump(toto, f, pickle.HIGHEST_PROTOCOL)

2 个答案:

答案 0 :(得分:2)

问题是,pickle会尝试检查您的对象是否有__getstate__方法,该方法可用于自定义对象的腌制方式。由于您的类未定义__getstate__方法,因此最终会调用__getattr__方法并返回None。 Pickle尝试调用此None值,这会产生您获得的异常。

有两种方法可以解决这个问题:

  1. 在班级中定义__getstate__和相应的__setstate__方法:

    def __getstate__(self):
        return vars(self)
    
    def __setstate__(self, state):
        vars(self).update(state)
    
  2. 重写您的__getattr__方法以更好地处理dunder-attributes(即抛出AttributeError而不是返回无意义的值):

    def __getattr__(self, attr: str) -> Any:
        """Return None for all unknown attributes"""
        if attr.startswith('__') and attr.endswith('__'):
            raise AttributeError
        return None
    

答案 1 :(得分:0)

如果您覆盖__getattr__,则可以通过实施__getstate____setstate__方法告诉您对象的准确结果

查看here了解更多信息

>>> import pickle
>>> class Toto:
...     def __init__(self, name:str):
...         self.name = name
...     def __getattr__(self, _: str):
...         """Return None for all unknown attributes"""
...         return None
...     def __getstate__(self): return self.__dict__
...     def __setstate__(self, d): self.__dict__.update(d)
... 
>>> 
>>> t=Toto()
>>> pickle.dumps(t)
b'\x80\x03c__main__\nToto\nq\x00)\x81q\x01}q\x02X\x04\x00\x00\x00nameq\x03X\x03\x00\x00\x00abcq\x04sb.'
>>>