2010-04-10 15 views
7

Quando ottengo un'eccezione di runtime dalla libreria standard, è quasi sempre un problema nel mio codice e non nel codice della libreria. C'è un modo per troncare la traccia dello stack di eccezioni in modo che non mostri il coraggio del pacchetto della libreria?Python: eliminazione delle tracce di stack nel codice della libreria?

Ad esempio, desidero ottenere:

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. 

e non questo:

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. 

aggiornamento: aggiunge l'answer con il codice, grazie al puntatore di Alex.

risposta

2

Grazie al puntatore di Alex, ecco 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() 

da cui si ricava questo stack trace:

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

Metti una prova non qualificata ... eccetto che nella parte superiore del tuo codice (es .: nella tua "main") o imposta sys.excepthook. Puoi quindi formattare la traccia dello stack come preferisci.

1

Il Traceback library è probabilmente quello che vuoi. Ecco un esempio che potrebbe aiutare:

import traceback 

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

(Questo ovviamente non funziona se c'è una deroga al di fuori della biblioteca e potrebbe non esattamente soddisfare le vostre esigenze, ma è un modo di usare la libreria traceback)

10

Il modulo traceback nella libreria standard di Python consente di emettere traceback degli errori in un modo che si adatta alle proprie preferenze, mentre un'eccezione si sta propagando. È possibile utilizzare questa potenza nel tratto except di un'istruzione try/except o in una funzione installata come sys.excepthook, che viene richiamata se e quando un'eccezione si propaga completamente; citando la documentazione:

In una sessione interattiva questo accade poco prima che il controllo viene restituito al prompt ; in un programma Python questo si verifica appena prima che il programma esca. La gestione di tali eccezioni di livello superiore può essere personalizzata da assegnando un'altra funzione a tre argomenti a sys.excepthook.

Ecco un semplice, ad esempio artificiale:

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

come si vede, senza bisogno di un try/except, si può facilmente limitare la traceback per (ad esempio) i primi tre livelli - anche se sappiamo per progetto che c'erano 9 livelli annidati quando è stata sollevata l'eccezione.

volete qualcosa di più sofisticato di un limite semplice sui livelli, quindi avrai bisogno di chiamare traceback.format_exception, che vi dà un elenco di linee piuttosto che stamparlo, poi "prugna" da tale elenco le linee che sono sui moduli non vuoi mai vedere nei tuoi traceback e, infine, emettere le righe rimanenti (in genere su sys.stderr, ma, qualunque sia! -).

+0

pura saggezza distillata, mescolato con un pizzico di stile ... grazie Alex! –

+0

@Mark, prego, grazie per il plauso! –

Problemi correlati