小编典典

使用Pickle / cPickle达到最大递归深度

python

背景:我正在使用最小构造算法构建一个Trie以表示字典。输入列表是430万个utf-8字符串,按字典顺序排序。生成的图是非循环的,最大深度为638个节点。我的脚本的第一行通过将递归限制设置为1100
sys.setrecursionlimit()

问题:我希望能够将Trie序列化到磁盘上,因此我可以将其加载到内存中,而不必从头开始重建(大约22分钟)。我已经尝试了pickle.dump()cPickle.dump(),同时使用了文本和二进制协议。每次,我都会得到如下所示的堆栈跟踪:

  File "/System/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/pickle.py", line 649, in save_dict
    self._batch_setitems(obj.iteritems())
  File "/System/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/pickle.py", line 663, in _batch_setitems
    save(v)
  File "/System/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/pickle.py", line 286, in save
    f(self, obj) # Call unbound method with explicit self
  File "/System/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/pickle.py", line 725, in save_inst
    save(stuff)
  File "/System/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/pickle.py", line 286, in save
    f(self, obj) # Call unbound method with explicit self
  File "/System/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/pickle.py", line 648, in save_dict
    self.memoize(obj)
RuntimeError: maximum recursion depth exceeded

我的数据结构相对简单: trie包含对开始状态的引用,并定义一些方法。
dfa_state包含一个布尔字段,一个字符串字段以及一个从label到state的字典映射。

我对pickle-的内部运作不是很熟悉-我的最大递归深度是否需要大于/等于n的trie深度才能达到n个?还是这可能是由我不知道的其他原因引起的?

更新: 将递归深度设置为3000并没有帮助,因此这种方法看起来前景不大。

更新2: 你们是对的;假设由于默认递归限制,泡菜将使用较小的嵌套深度,这是我的短视。10,000个窍门。


阅读 281

收藏
2020-12-20

共1个答案

小编典典

文档

尝试腌制高度递归的数据结构可能会超出最大递归深度,在这种情况下将引发RuntimeError。您可以使用小心提高此限制sys.setrecursionlimit()

尽管您的trie实现可能很简单,但它使用递归,并在转换为持久性数据结构时可能导致问题。

我的建议是继续提高递归限制,以查看您正在使用的数据和所使用的trie实现是否有上限。

除此之外,如果可能的话,您可以尝试将树实现更改为“较少递归”,或者编写 一个 内置了数据持久性 的附加实现
(在实现中使用泡菜和架子)。希望能有所帮助

2020-12-20