2012-07-20 14 views
31

Quiero manejar AssertionError s tanto para ocultar partes innecesarias de la traza de la pila del usuario como para imprimir un mensaje sobre por qué ocurrió el error y qué debe hacer el usuario al respecto.¿Cómo manejar AssertionError en Python y descubrir en qué línea o enunciado se produjo?

¿Hay alguna manera de averiguar en qué línea o declaración falló el assert dentro del bloque 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) 

yo no quiero tener que añadir esto a cada declaración afirman:

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

porque se repite la información.

+7

Dos problemas. Primero, si tiene problemas para identificar dónde ocurre la excepción en su 'try..except', eso es una señal de que su bloque' try..except' es demasiado grande. En segundo lugar, el tipo de cosa que debe ser atrapada por 'assert' no es algo que el usuario deba ver nunca. Si ven un 'AssertionError', el curso de acción apropiado es que se comuniquen con el programador y digan "WTF ?!". –

+2

@John Y, pareces confundido. Usted está diciendo que 'AssertionError's no debería ser visto por el usuario, y luego lo que el usuario debería hacer cuando lo vea. No puede ser ambos! – devtk

+3

BTW: las afirmaciones deben ser sobre la estructura de su código, es decir, una afirmación debe fallar solo si tiene un error en su software. No deben usarse para verificar la entrada del usuario. Puede considerar usar una excepción diferente para esta aplicación. –

Respuesta

47

utilizar el módulo 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

El módulo de rastreo y sys.exc_info son excesivos para rastrear el origen de una excepción. Eso es todo en el rastreo predeterminado. Así que en lugar de llamar a la salida (1) acaba de volver a subir:

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

que da el siguiente resultado, que incluye la declaración infractor y número de línea:

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 

Del mismo modo el módulo de registro hace que sea fácil de conectarse un rastreo para cualquier excepción (incluidos los que se detectan y nunca se vuelven a generar):

import logging 

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