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

Mar*_*son 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.
Run Code Online (Sandbox Code Playgroud)

而不是这个:

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.
Run Code Online (Sandbox Code Playgroud)

更新:通过Alex的指针添加了代码的答案.

Ale*_*lli 10

Python标准库中的回溯模块允许您以符合您喜欢的方式发出错误回溯,同时传播异常.您可以在使用这个权力或者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
Run Code Online (Sandbox Code Playgroud)

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

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


Mar*_*son 5

感谢 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()
Run Code Online (Sandbox Code Playgroud)

这会产生这个堆栈跟踪:

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
Run Code Online (Sandbox Code Playgroud)