【问题标题】:Why Python's defaultdict behaves weirdly with pickle?为什么 Python defaultdict 对 pickle 的行为很奇怪?
【发布时间】:2019-12-19 21:24:06
【问题描述】:

我正在使用 PySpark,它使用 Python 的 pickle 来序列化对象。我的用例有一个嵌套的defaultdict 数据结构,例如:

from collections import defaultdict

nested_dict = defaultdict(lambda: defaultdict(lambda: defaultdict(int)))

腌制这个 nested defaultdict 结构给出

PicklingError: Can't pickle at 0x1076cc9d8>: __main__ 上的属性查找失败

在一个 SO 答案中有一个 wonderful workaround

我一直在尝试这样做,并想知道它会导致一些不直观的功能/用法。例如,

import pickle

def dd():
    def di():
        return defaultdict(int)
    return defaultdict(di)

nested = defaultdict(dd)
pickle.loads(pickle.dumps(nested))

有效,但跟随不起作用

def nested_dd():
    def dd():
        def di():
            return defaultdict(int)
        return defaultdict(di)
    return defaultdict(dd)

pickle.loads(pickle.dumps(nested_dd()))

它给了

AttributeError: Can't pickle local object nested_dd.<locals>.dd

这里发生了什么?

【问题讨论】:

  • 尝试使用pickle.loads(pickle.dumps(nested_dd)) 而不是pickle.loads(pickle.dumps(nested_dd()))
  • @shaikmoed:没有变化。我想要的任何方式都是 3 级深度 defaultdict,所以无论如何我都会实例化一个 nested_dd。当我尝试nested_dd3 = nested_dd() 时,我得到了同样的错误。

标签: python python-3.x serialization pickle defaultdict


【解决方案1】:

虽然other serialization techniques 存在,但您只能pickle 可以由from … import foo 找到的函数(因为这就是解开函数所做的)。如果外部 defaultdict 不为空,您的“工作”示例将失败,因为每个嵌套字典都有一个本地函数作为 默认工厂。

在这种情况下,由于这些函数都没有关闭任何东西,因此您可以在顶层编写它们。

【讨论】:

    猜你喜欢
    • 2021-06-01
    • 1970-01-01
    • 2019-09-06
    • 2011-08-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多