无法pickle empty ordered_set

kuz*_*roo 4 python pickle

我正在使用从这个答案链接到的ordered_set模块的 1.2版本(目前是最新版本).我一直在做一些奇怪的行为,并追溯到这个:

from ordered_set import OrderedSet
import pickle

os_orig = OrderedSet()
print os_orig # 'OrderedSet'
print os_orig.items # '[]'
pickled = pickle.dumps(os_orig)
loaded = pickle.loads(pickled)
print loaded
Run Code Online (Sandbox Code Playgroud)

哪个加注AttributeError: 'OrderedSet' object has no attribute 'items'.如果OrderedSet不为空,一切都会好起来的.

不幸的是,当谈到泡菜时,我总是在脑子里 - 出了什么问题?

编辑:我应该补充一点,该模块似乎支持泡菜.来自自述文件:"添加了一个__getstate__,__setstate__所以可以腌制"

Mar*_*ers 8

OrderedSet当set为空时,对于中断的pickle支持,因为返回的状态__getstate__基本上是空的:

>>> OrderedSet().__getstate__()
[]
Run Code Online (Sandbox Code Playgroud)

当再次加载pickle时,pickle模块最终没有调用__setstate__,因为__getstate__返回值为空.不调用__setstate__意味着OrderedSet.__init__()永远不会调用该方法,并且您有一个损坏的对象.查看__setstate__文档:

注意:对于新样式的类,如果__getstate__()返回false值,__setstate__()则不会调用该方法.

空列表是假值.

作者必须只测试酸洗非空 OrderedSet()实例,这样可以正常工作.

您可以通过替换__getstate____setstate__方法来解决问题:

def __getstate__(self):
    return (list(self),)
OrderedSet.__getstate__ = __getstate__

def __setstate__(self, state):
    if isinstance(state, tuple):
        state = state[0]
    self.__init__(state)
OrderedSet.__setstate__ = __setstate__
Run Code Online (Sandbox Code Playgroud)

现在返回一个非空的,1元素的元组,强制甚至pickle调用__setstate__空集.该__setstate__仍将接受以前的咸菜格式,一个列表对象.

我已将此报告为项目错误,因为已关闭已解决.