在递归函数中引发错误时,如何避免长堆栈跟踪?

时间:2013-11-16 12:08:16

标签: python exception logging recursion

考虑以下功能:

def fact(x):

    if x == 1:
        return 1

    if x == 2:
        raise Exception("some error")

    return fact(x-1) * x

调用fact(100)将产生一个堆栈跟踪,其中包含100个对“fact”函数的引用。如何简化堆栈跟踪以帮助调试?可以改变一些东西来避免这个大堆栈吗?

注意:由于我刚才写的一些代码,这是一个假设的情况。

2 个答案:

答案 0 :(得分:2)

您可以尝试traceback

这里我写了一些测试代码。使用Python 3.3.2

进行测试
import sys
import traceback

def fact(x):
    if x == 0:
        raise Exception("test exception")
    else:
        return fact(x - 1)

def main():
    fact(5)

if __name__ == "__main__":
    try:
        main()
    except:
        (_type, _value, _traceback) = sys.exc_info()
        tb = traceback.extract_tb(_traceback)
        lst = traceback.format_list(tb) 
        lst += [""] # assuming there was no "" in lst
        last_str = None
        last_count = 0
        for s in lst:
            if s == last_str:
                last_count += 1
            else:
                if last_str == None:
                    print(s, end="")
                else:
                    if last_count > 2:
                        print("...omitted %d same items"%(last_count - 2))
                    if last_count > 1:
                        print(last_str, end="")
                    print(s, end="")
                last_str = s
                last_count = 1

测试输出:

  File "test.py", line 15, in <module>
    main()
  File "test.py", line 11, in main
    fact(5)
  File "test.py", line 8, in fact
    return fact(x - 1)
...omitted 3 same items
  File "test.py", line 8, in fact
    return fact(x - 1)
  File "test.py", line 6, in fact
    raise Exception("test exception")

答案 1 :(得分:1)

如果您在3-arg catch中捕获异常或者调用sys.exc_info(),那么您可以访问traceback对象,并且可以使用{{1}一直向上移动}字段。您可以根据需要以任何方式构建另一组回溯。重新启动异常。