2010-03-01 11 views
17

Quando si verifica un'eccezione in Python, è possibile ispezionare lo stack? Puoi determinarne la profondità? Ho esaminato il modulo traceback, ma non riesco a capire come usarlo.Come si può controllare a livello di codice la traccia dello stack di un'eccezione in Python?

Il mio obiettivo è rilevare eventuali eccezioni che si verificano durante l'analisi di un'espressione di eval, senza interferire con le eccezioni generate da eventuali funzioni che potrebbe aver chiamato. Non rimproverarmi per aver usato eval. Non è stata una mia decisione.

NOTA: Voglio farlo a livello di programmazione, non in modo interattivo.

risposta

13

traceback è sufficiente - e suppongo che la documentazione lo descriva piuttosto bene. esempio semplificato:

import sys 
import traceback 

try: 
    eval('a') 
except NameError: 
    traceback.print_exc(file=sys.stdout) 
+2

Non sto tentando di stampare il traceback. Sto cercando di ispezionarlo. In che modo questo mi dice se l'eccezione si è verificata nel testo stesso o in una funzione chiamata dal testo valutato? –

+0

SyntaxError verrà generato se il testo 'eval' è errato. –

+0

Molti tipi di errori possono essere lanciati se il testo di valutazione è sbagliato.Ho finito per usare inspect e osservare la profondità del traceback per vedere se l'errore era causato dalla valutazione del testo originale o se si trovava nel corpo di una funzione chiamata. –

0

Oltre alla risposta di AndiDog su inspect, si noti che pdb consente di navigare su e giù per lo stack, ispezionando i locali e cose del genere. La fonte nella libreria standard pdb.py potrebbe esserti utile nell'imparare come fare tali cose.

4

Mi piace il modulo traceback.

È possibile ottenere un oggetto traceback utilizzando sys.exc_info(). Quindi è possibile utilizzare quell'oggetto per ottenere un elenco pre-elaborato di voci di traceback utilizzando traceback.extract_tb(). Poi si può ottenere un elenco leggibile utilizzando traceback.format_list() come segue:

import sys 
import traceback, inspect 

try: 
    f = open("nonExistant file",'r') 
except: 
    (exc_type, exc_value, exc_traceback) = sys.exc_info() 
    #print exception type 
    print exc_type 
    tb_list = traceback.extract_tb(sys.exc_info()[2]) 
    tb_list = traceback.format_list(tb_list) 
    for elt in tb_list: 
     print elt 
     #Do any processing you need here. 

vedere il modulo sys: http://docs.python.org/library/sys.html

e il modulo traceback: http://docs.python.org/library/traceback.html

1

È possibile definire una tale funzione():

e chiamarlo dai tuoi moduli così:

raiseErr() 

La funzione raiseErr stampa le informazioni relative al luogo in cui è stata chiamata.

più elaborati, è possibile farlo:

import inspect, traceback 
A = [inspect.getframeinfo(f[0]) for f in inspect.stack()] 
print "traceback structure fields:", filter(lambda s: s[0] != '_', dir(A[0])) 
print A[0].filename, A[0].lineno 
for f in inspect.stack(): 
    F = inspect.getframeinfo(f[0]) 
    print '-', F.filename, F.lineno, '\t', F.code_context[0].strip() 

Altra possibilità è quella di definire questa funzione:

def tr(): 
    print '* - '*10, 
    print sys._getframe(1).f_code.co_name 

e chiamarlo nel luogo in cui si desidera che la traccia. Se si desidera tutta la traccia, creare un iteratore da 1 su in _getframe(1).