我正在使用 PySpark,它使用 Python 的 pickle 来序列化对象。我的用例有一个嵌套的
defaultdict
数据结构,例如:
from collections import defaultdict
nested_dict = defaultdict(lambda: defaultdict(lambda: defaultdict(int)))
腌制这个
nested
defaultdict
结构给出
PicklingError:无法在 0x1076cc9d8> 进行腌制>:__main__ 上的属性查找失败
有一个很棒的解决方法在一个SO答案中。
我一直在尝试这样做,并对它导致的一些不直观的功能/用法感到好奇。例如,
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:无法腌制本地对象
nested_dd.<locals>.dd
这里发生了什么事?
虽然存在其他序列化技术,但您只能
pickle
可以通过from … import foo
找到的函数(因为这就是unpickling函数所做的)。如果外部 defaultdict
不为空,您的“工作”示例将会失败,因为每个嵌套字典都会有一个本地函数作为 its 默认工厂。
在这种情况下,由于这些函数都没有关闭任何东西,因此您可以将它们写在顶层。
还有另一种非常简单的解决方法可能适合您的用例,但我没有在任何答案中看到。唯一需要注意的是,如果在 pickle 之后继续扩展字典,您将丢失默认值。只需做:
pickle.dump(dict(nested_dict))