在python 2.7中增加递归限制和堆栈大小

时间:2017-03-14 14:25:36

标签: python-2.7 recursion stack ipython spyder

我正在使用大型树,需要增加Python 2.7的递归限制。

使用sys.setrecursionlimit(10000)崩溃我的内核,所以我想我需要增加堆栈大小。

但是我不知道堆栈大小应该有多大。我尝试100 MiB像这样threading.stack_size(104857600),但内核仍然死了。给它1 GiB会抛出错误。

我还没有使用threading模块,所以当我将上述语句放在脚本的开头时,我使用它是错误的吗?我没有做任何类型的并行处理,一切都在同一个线程中完成。

我的电脑有128 GB的物理RAM,在Spyder中运行Windows 10,iPython控制台。

显示的错误只是:

  

内核死了,重启

没有更多。

编辑:

重现问题的完整代码。树的构建很好地认为它需要很长时间,在将整个树读入字典时,内核仅在treeToDict()的递归执行期间死亡。也许这个函数的代码有问题。树是非二叉树:

import pandas as pd
import threading
import sys
import random as rd
import itertools as it
import string
threading.stack_size(104857600)
sys.setrecursionlimit(10000)

class treenode:
    # class to build the tree
    def __init__(self,children,name='',weight=0,parent=None,depth=0):
        self.name = name
        self.weight = weight
        self.children = children
        self.parent = parent
        self.depth = depth
        self.parentname = parent.name if parent is not None else ''

def add_child(node,name):
    # add element to the tree
    # if it already exists at the given node increase weight
    # else add a new child
    for i in range(len(node.children)):
        if node.children[i].name == name:
            node.children[i].weight += 1
            newTree = node.children[i]
            break
    else:
        newTree = treenode([],name=name,weight=1,parent=node,depth=node.depth+1)
        node.children.append(newTree)
    return newTree

def treeToDict(t,data):
    # read the tree into a dictionary
    if t.children != []:
        for i in range(len(t.children)):
            data[str(t.depth)+'_'+t.name] = [t.name, t.children[i].name, t.depth, t.weight, t.parentname]
    else:
        data[str(t.depth)+'_'+t.name] = [t.name, '', t.depth, t.weight, t.parentname]
    for i in range(len(t.children)):
        treeToDict(t.children[i],data)

# Create random dataset that leads to very long tree branches:
# A is an index for each set of data B which becomes one branch
rd.seed(23)
testSet = [''.join(l) for l in it.combinations(string.ascii_uppercase[:20],2)]
A = []
B = []
for i in range(10):
    for j in range(rd.randint(10,6000)):
        A.append(i)
        B.append(rd.choice(testSet))
dd = {"A":A,"B":B}
data = pd.DataFrame(dd)
# The maximum length should be above 5500, use another seed if it's not:
print data.groupby('A').count().max()

# Create the tree
root = treenode([],name='0')
for i in range(len(data.values)):
    if i == 0:
        newTree = add_child(root,data.values[i,1])
        oldses = data.values[i,0]
    else:
        if data.values[i,0] == oldses:
            newTree = add_child(newTree,data.values[i,1])
        else:
            newTree = add_child(root,data.values[i,1])
            oldses = data.values[i,0]

result={}
treeToDict(root,result)

PS:我知道treeToDict()函数有问题,因为它会覆盖条目,因为可能存在重复的密钥。对于这个错误,这个错误并不重要。

1 个答案:

答案 0 :(得分:4)

根据我的经验,你遇到的问题不是堆栈大小,而是算法本身。

可以在没有递归的情况下实现树遍历过程。您应该实现基于堆栈的深度/广度优先搜索算法。 类似Python的伪代码可能如下所示:

stack = []
def traverse_tree(root):
  stack.append(root)
  while stack:
    cur = stack.pop()
    cur.do_some_awesome_stuff()
    stack.append(cur.get_children())

这种方法具有令人难以置信的可扩展性,允许您处理任何树木。

进一步阅读时,您可以尝试thisthat