2010-04-10 35 views
7

当我从标准库中得到运行时异常时,它几乎总是我的代码中的问题,而不是库代码中的问题。有没有办法截断异常堆栈跟踪,以便它不显示库包的内部?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的代码,这要归功于从亚历克斯的指针。

回答

2

感谢亚历克斯指针,这里的德codez:

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 
0

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

1

Traceback library可能是你想要的。这里有一个例子,可以帮助:

import traceback 

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

(这是否有库外的异常显然是行不通的,并且可能不完全满足您的需求,但它的使用回溯库单程)

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,但是,无论如何 - )。

+0

纯蒸馏水智慧,用的风格破折号混合...感谢亚历克斯! – 2010-04-11 06:44:06

+0

@Mark,不客气 - 感谢您的荣誉! – 2010-04-11 15:32:28