2010-04-10 7 views
7

Cuando obtengo una excepción de tiempo de ejecución de la biblioteca estándar, casi siempre es un problema en mi código y no en el código de la biblioteca. ¿Hay alguna manera de truncar el seguimiento de la pila de excepción para que no muestre las agallas del paquete de la biblioteca?Python: eliminando los rastros de pila en el código de la biblioteca?

Por ejemplo, me gustaría conseguir esto:

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. 

y no esto:

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. 

actualización: añade un answer con el código, gracias al puntero de Alex.

Respuesta

2

Gracias al puntero de Alex, aquí está teh 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() 

que produce este seguimiento de la pila:

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

Ponga un intento sin reservas ... excepto en la parte superior de su código (es decir: en su "principal") o establezca sys.excepthook. A continuación, puede formatear el trazado de la pila como lo desee.

1

El Traceback library es probablemente lo que usted desea. He aquí un ejemplo que podría ayudar:

import traceback 

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

(Obviamente, esto no funcionará si hay una excepción fuera de la biblioteca, y podría no ajustarse exactamente a sus necesidades, pero es una forma de usar la biblioteca de rastreo)

10

El módulo traceback de la biblioteca estándar de Python le permite emitir identificaciones de error de acuerdo con su gusto, mientras se propaga una excepción. Puede utilizar este poder en el segmento except de una declaración try/except, o en una función que haya instalado como sys.excepthook, que recibe una llamada si y cuando una excepción se propaga por completo; citando los documentos:

En una sesión interactiva esto sucede justo antes de se devuelve el control a la línea de ; en un programa de Python, esto ocurre justo antes de que el programa salga. El manejo de dichas excepciones de nivel superior se puede personalizar por asignando otra función de tres argumentos a sys.excepthook.

Aquí está un ejemplo sencillo, artificial:

>>> 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 

como se ve, sin necesidad de un try/except, puede limitar fácilmente el rastreo a (por ejemplo) los primeros tres niveles - a pesar de que sabemos por diseño que había 9 niveles anidados cuando se planteó la excepción.

Desea algo más sofisticado que un límite simple de niveles, por lo que deberá llamar al traceback.format_exception, que le proporciona una lista de líneas en lugar de imprimirla, luego "podar" de esa lista las líneas que tratan sobre módulos nunca querrá ver en sus trazas, y finalmente emitirá las líneas restantes (generalmente a sys.stderr, pero, lo que sea! -).

+0

sabiduría destilada pura, mezclado con un toque de estilo ... gracias Alex! –

+0

@Mark, de nada, ¡gracias por las felicitaciones! –

Cuestiones relacionadas