Python Pickler - 递归深度超过限制

6

我试图pickle我的细胞自动机类的实例,但是我得到了这个错误:

RuntimeError: maximum recursion depth exceeded while calling a Python object

我的元胞自动机由细胞列表(以及其他一些东西)组成,每个细胞都有指向其邻居的指针。在这个特定的自动机中,有256个细胞。现在,我知道pickler应该能够识别已经pickled的对象。
根据文档:
* pickle模块跟踪它已经序列化的对象,以便稍后对相同对象的引用不会再次序列化。
所以我不知道为什么会超出最大递归深度。
我认为可能是pickler进行了深度优先的pickling,因此它首先遵循指针,超出递归堆栈然后引发异常。我知道我可以使用sys.setrecursionlimit()来扩展最大递归深度,但我不认为这是一个好的、可扩展的解决方案。
第一个问题:pickler是否进行深度优先的pickling?
第二个问题:如何防止此异常?

你有可以发布的任何代码吗? - Aswin Murugesh
是的,pickle 是深度优先的。不幸的是,我认为没有绕过这个问题的方法。尝试使用 cPickle,但它可能会产生相同的错误。 - Elmar Peise
@AswinMurugesh 实际上我有太多的代码要发布。但是如果你感兴趣,这里有一些关键文件: 邻域 细胞 腌制 例如:cPickle是相同的,我之前试过了。我担心会得到这个答案。 - sjudǝʊ
@ExP,你有关于pickle内部工作原理的更具体信息/资源吗?也许可以创建pickler的子类?总有办法的。我只需要仔细研究一下 :) - sjudǝʊ
@sjudǝʊ 如果您查看pickle在给定虚拟数据的输出结果,您会发现它采用深度优先的方式。由于我猜测该格式不允许前向引用,我很抱歉您将无法修改或创建其子类以解决您的问题... - Elmar Peise
可能是 Hitting Maximum Recursion Depth Using Python's Pickle / cPickle 的重复问题。 - Ciro Santilli OurBigBook.com
1个回答

6
所以,就像@ExP所说的那样,pickler进行深度优先的序列化,这会导致递归超出异常。无论如何,我在这里找到了解决方案bugs.python.org。也就是说,对于Python 3.1,即使是像图形这样的递归数据,pickler也可以正常工作。

还有一个不太优雅但需要更多时间来序列化一些递归数据的简单解决方案(只需要几行代码)。链接here

看起来,现在是慢慢开始转向Python 3的时候了。希望这个答案对某人有用。


如果您最终使用了 http://bugs.python.org/issue2480 中提供的修复方法,请确保使用非递归拾取器修复版 python 文件,而不是其他文件。另外需要注意的是,这个 pickle 解决方案的压缩比普通 pickle 要低得多,因此您的 pickle 文件会更大。感谢您提供的解决方案! - kevin948
2
尽管这个issue2480版本可以工作,但是由于它使用了list.pop(0)和list.extend,在处理大型结构时非常低效。在我的大型数据结构上,序列化需要10个小时。重写以使用deque将其缩短到4分钟。 - strubbly

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接