2012-07-20 8 views
31

Voglio gestire AssertionError s per nascondere le parti non necessarie dello stack trace dall'utente e per stampare un messaggio sul motivo per cui si è verificato l'errore e su cosa l'utente deve fare al riguardo.Come gestire AssertionError in Python e scoprire in quale linea o istruzione si è verificato?

C'è un modo per scoprire su quale riga o istruzione lo assert è fallito nel blocco except?

try: 
    assert True 
    assert 7 == 7 
    assert 1 == 2 
    # many more statements like this 
except AssertionError: 
    print 'Houston, we have a problem.' 
    print 
    print 'An error occurred on line ???? in statement ???' 
    exit(1) 

Io non voglio avere per aggiungere questo per ogni affermazione assert:

assert 7 == 7, "7 == 7" 

perché ripete informazioni.

+7

Due problemi. Innanzitutto, se hai problemi a identificare dove sta accadendo l'eccezione nel tuo 'try..except', questo è un segnale che il tuo blocco 'try..except' è troppo grande. Secondo, il tipo di cosa che deve essere catturato da "assert" non è qualcosa che l'utente dovrebbe mai vedere. Se vedono un "AssertionError", il modo corretto di agire è che contattino il programmatore e dica "WTF ?!". –

+2

@ John Y, sembri confuso. Stai dicendo che "AssertionError's non dovrebbe essere visto dall'utente, e quindi cosa l'utente dovrebbe fare quando ne vede uno. Non può essere entrambi! – devtk

+3

BTW: Le asserzioni dovrebbero riguardare la struttura del tuo codice, ovvero un assert dovrebbe fallire solo se hai un bug nel tuo software. Non dovrebbero essere usati per controllare l'input dell'utente. Si potrebbe prendere in considerazione l'utilizzo di un'eccezione diversa per questa applicazione. –

risposta

47

utilizzare il modulo traceback:

import sys 
import traceback 

try: 
    assert True 
    assert 7 == 7 
    assert 1 == 2 
    # many more statements like this 
except AssertionError: 
    _, _, tb = sys.exc_info() 
    traceback.print_tb(tb) # Fixed format 
    tb_info = traceback.extract_tb(tb) 
    filename, line, func, text = tb_info[-1] 

    print('An error occurred on line {} in statement {}'.format(line, text)) 
    exit(1) 
1

Il modulo traceback e sys.exc_info sono eccessivo per rintracciare la fonte di un'eccezione. Questo è tutto nel traceback predefinito. Così, invece di chiamare exit (1) appena ri-raise:

try: 
    assert "birthday cake" == "ice cream cake", "Should've asked for pie" 
except AssertionError: 
    print 'Houston, we have a problem.' 
    raise 

che dà il seguente risultato che include la dichiarazione incriminata e numero di linea:

Houston, we have a problem. 
Traceback (most recent call last): 
    File "/tmp/poop.py", line 2, in <module> 
    assert "birthday cake" == "ice cream cake", "Should've asked for pie" 
AssertionError: Should've asked for pie 

Allo stesso modo il modulo di registrazione rende facile effettuare il login un traceback per qualsiasi eccezione (compresi quelli che vengono catturati e mai controrilanciati):

import logging 

try: 
    assert False == True 
except AssertionError: 
    logging.error("Nothing is real but I can't quit...", exc_info=True) 
Problemi correlati