python - 无法 pickle 空的 ordered_set

标签 python pickle

我使用的是 the ordered_set module 的 1.2 版(目前是最新的)链接至 this answer .我一直有一些奇怪的行为,并已将其追溯到:

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

这会引发 AttributeError: 'OrderedSet' object has no attribute 'items'。如果 OrderedSet 不为空,则一切正常。

不幸的是,当谈到 pickle 时,我有点头疼——哪里出了问题?

编辑:我应该补充一点,该模块似乎支持 pickle。来自自述文件:“添加了一个 __getstate____setstate__ 以便它可以被 pickle ”

最佳答案

OrderedSet 的 pickle 支持在集合为空时中断,因为 __getstate__ 返回的状态本质上是空的:

>>> OrderedSet().__getstate__()
[]

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

Note: For new-style classes, if __getstate__() returns a false value, the __setstate__() method will not be called.

空列表是错误值。

作者一定只测试了 pickling 非空 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__

现在返回一个非空的 1 元素元组,强制 pickle 调用 __setstate__,即使对于空集也是如此。 __setstate__ 仍将接受以前的 pickle 格式,一个列表对象。

我已将其报告为 bug with the project , 由于已解决而关闭。

关于python - 无法 pickle 空的 ordered_set,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24846605/

相关文章:

python - 获取放置在字符串内的信息 'randomly'

python - 查找子字符串,避免使用递归函数

python - 什么是用垃圾收集语言进行计算几何(如 CGAL)的好库?

python - 为什么 dill 比 numpy 数组的 pickle 更快更磁盘高效

python - pickle 无法导入已存在的模块?

python - 为什么 Python 不包含从文件名加载 pickle 的函数?

python - 无法导入名称 FormWizard

python - 我如何在python中进行幂运算?

python - 为什么将 pickle 文件加载到内存中会占用更多空间?

python - 解压后系统使用大量内存