Python:将堆栈跟踪消除到库代码中?

时间:2010-04-10 23:28:45

标签: python

当我从标准库中获得运行时异常时,它几乎总是我的代码中的问题,而不是库代码中的问题。有没有办法截断异常堆栈跟踪,以便它不显示库包的内容?

例如,我想得到这个:

Traceback (most recent call last):
  File "./lmd3-mkhead.py", line 71, in <module>
    main()
  File "./lmd3-mkhead.py", line 66, in main
    create()
  File "./lmd3-mkhead.py", line 41, in create
    headver1[depotFile]=rev
TypeError: Data values must be of type string or None.

而不是这个:

Traceback (most recent call last):
  File "./lmd3-mkhead.py", line 71, in <module>
    main()
  File "./lmd3-mkhead.py", line 66, in main
    create()
  File "./lmd3-mkhead.py", line 41, in create
    headver1[depotFile]=rev
  File "/usr/anim/modsquad/oses/fc11/lib/python2.6/bsddb/__init__.py", line 276, in __setitem__
    _DeadlockWrap(wrapF)  # self.db[key] = value
  File "/usr/anim/modsquad/oses/fc11/lib/python2.6/bsddb/dbutils.py", line 68, in DeadlockWrap
    return function(*_args, **_kwargs)
  File "/usr/anim/modsquad/oses/fc11/lib/python2.6/bsddb/__init__.py", line 275, in wrapF
    self.db[key] = value
TypeError: Data values must be of type string or None.

更新:添加了answer代码,感谢Alex的指针。

4 个答案:

答案 0 :(得分:10)

Python标准库中的traceback模块允许您以符合您喜欢的方式发出错误回溯,同时传播异常。您可以在except / try语句的except段中使用此功能,也可以在已安装为sys.excepthook的功能中使用此功能,该功能会在时间和时间被调用一个异常一直传播;引用文档:

  

在交互式会话中会发生这种情况   就在控制权返回之前   提示;在这个Python程序中   在程序退出之前发生。   处理这样的顶级   例外可以定制   分配另一个三个参数   函数到sys.excepthook。

这是一个简单的人为例子:

>>> import sys
>>> import traceback
>>> def f(n):
...   if n<=0: raise ZeroDivisionError
...   f(n-1)
... 
>>> def excepthook(type, value, tb):
...   traceback.print_exception(type, value, tb, 3)
... 
>>> sys.excepthook = excepthook
>>> f(8)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in f
  File "<stdin>", line 3, in f
ZeroDivisionError

如您所见,不需要try / except,您可以轻松地将回溯限制为(例如)前三个级别 - 即使我们已经通过设计知道有9个嵌套提出异常时的等级。

你想要比级别上的简单限制更复杂的东西,所以你需要调用traceback.format_exception,它给你一个行列表而不是打印它,然后从那个列表中“修剪”那些行是关于你永远不想在你的追溯中看到的模块,最后发出剩余的行(通常是sys.stderr,但是,无论如何! - )。

答案 1 :(得分:2)

感谢Alex的指针,这里是代码:

def trimmedexceptions(type, value, tb, pylibdir=None, lev=None):
    """trim system packages from the exception printout"""
    if pylibdir is None:
        import traceback, distutils.sysconfig
        pylibdir = distutils.sysconfig.get_python_lib(1,1)
        nlev = trimmedexceptions(type, value, tb, pylibdir, 0)
        traceback.print_exception(type, value, tb, nlev)
    else:
        fn = tb.tb_frame.f_code.co_filename
        if tb.tb_next is None or fn.startswith(pylibdir):
            return lev
        else:
            return trimmedexceptions(type, value, tb.tb_next, pylibdir, lev+1)

import sys
sys.excepthook=trimmedexceptions

# --- test code ---

def f1(): f2()
def f2(): f3()
def f3():
    import xmlrpclib
    proxy = xmlrpclib.ServerProxy('http://nosuchserver')
    proxy.f()

f1()

产生此堆栈跟踪:

Traceback (most recent call last):
  File "./tsttraceback.py", line 47, in <module>
    f1()
  File "./tsttraceback.py", line 40, in f1
    def f1(): f2()
  File "./tsttraceback.py", line 41, in f2
    def f2(): f3()
  File "./tsttraceback.py", line 45, in f3
    proxy.f()
gaierror: [Errno -2] Name or service not known

答案 2 :(得分:1)

Traceback library可能就是你想要的。以下是一个可能有用的示例:

import traceback

try:
    your_main()
except:
    lines = traceback.format_exc()
    print lines[:lines.find('File "/usr')]

(如果库外有异常,这显然不会起作用,可能不完全符合您的需求,但这是使用回溯库的一种方式)

答案 3 :(得分:0)

进行不合格的尝试...除了代码顶部(即:在“主要”中)或设置sys.excepthook。然后,您可以根据需要格式化堆栈跟踪。