2009-01-31 11 views
13

Me preguntaba cómo hacer que python falle de una manera definida por el usuario en todos los posibles errores.¿Cómo hacer que python falle con elegancia?

Por ejemplo, estoy escribiendo un programa que procesa una lista (grande) de elementos, y algunos de los artículos pueden no estar en el formato que definí. Si python detecta un error, actualmente solo escupe un feo mensaje de error y detiene todo el proceso. Sin embargo, quiero que muestre el error en algún lugar junto con algún contexto y luego pase al siguiente elemento.

¡Si alguien puede ayudarme con esto, sería muy apreciado!

¡Muchas gracias!

Jason

Respuesta

23

Las siguientes son algunas estrategias básicas que utilizo regularmente en mi más de lo trivial scripts y aplicaciones de tamaño medio.

Consejo 1: Detecte el error en todos los niveles donde tenga sentido continuar el procesamiento. En tu caso, puede estar en el interior del bucle. No tiene que proteger cada línea o cada llamada de función, sino solo los lugares donde hace la diferencia para sobrevivir el error.

Consejo 2: Utilice el módulo de registro para informar qué sucedió de manera configurable independientemente de cómo se compone el módulo con otros módulos en aplicaciones más grandes. Comience a importar el registrador de raíz en su módulo, luego, utilizándolo en algunos lugares diferentes, eventualmente podrá descubrir una jerarquía de registro más sensible.

import logging 
logger = logging.getLogger() 

for item in items: 
    try: 
     process(item) 
    except Exception, exc: 
     logger.warn("error while processing item: %s", exc) 

Consejo 3: definir una "excepción de aplicación", con el tiempo es posible que desee definir una jerarquía de dicha excepción, pero esto es mejor descubierto cuando se presenta la necesidad.Use tales excepciones para "salirse" cuando los datos con los que está tratando no son los esperados o para señalar situaciones inconsistentes, mientras los separa de la excepción estándar normal que surge de errores o errores regulares fuera del dominio modelado (errores IO) etc.)

class DomainException(Exception): 
    """Life is not what I expected""" 

def process(item): 
    # There is no way that this item can be processed, so bail out quickly. 
    # Here you are assuming that your caller will report this error but probably 
    # it will be able to process the other items. 
    if item.foo > item.bar: 
     raise DomainException("bad news") 

    # Everybody knows that every item has more that 10 wickets, so 
    # the following instruction is assumed always being successful. 
    # But even if luck is not on our side, our caller will be able to 
    # cope with this situation and keep on working 
    item.wickets[10] *= 2 

La función principal es el punto de control externo: finalmente, trate aquí las posibles formas en que terminó su tarea. Si esto no fue un script de shell (pero por ejemplo, el procesamiento debajo de un diálogo en una aplicación UI o una operación después de un POST en una aplicación web) solo la forma en que informa el error cambia (y el uso del método de registro separa completamente la implementación del procesamiento desde su interfaz).

def main(): 
    try: 
     do_all_the_processing() 
     return 0 
    except DomainException, exc: 
     logger.error("I couldn't finish. The reason is: %s", exc) 
     return 1 
    except Exception, exc: 
     logger.error("Unexpected error: %s - %s", exc.__class__.__name__, exc) 
     # In this case you may want to forward a stacktrace to the developers via e-mail 
     return 1 
    except BaseException: 
     logger.info("user stop") # this deals with a ctrl-c 
     return 1 

if __name__ == '__main__': 
    sys.exit(main()) 
+0

entonces, ¿cómo obtengo un trackback en los registros? – FurtiveFelon

+0

Consulte la documentación del módulo de registro en http://docs.python.org/library/logging.html#logging.debug - Cada función de registro tiene un parámetro exc_info que le dice si desea registrar el rastreo. Puede registrar un controlador de registro para que en cada logger.critical() se envíe un rastreo a los desarrolladores. – piro

8

El feo mensaje significa que se produce una excepción. Debes atrapar la excepción.

Un buen lugar para comenzar es la Python tutorial's section on exceptions.

Básicamente lo que necesita para envolver el código en un bloque try...except así:

try: 
    do_something_dangerous() 
except SomeException: 
    handle_the_error() 
3

uso try... except idioma

try: 
    # code that possibly breaks 
except RelevantError:   # you need to know what kind of errors you code might produce 
    # show your message 
+0

O puede ver el tipo de excepción para atrapar (casi) todas las excepciones de error. ("Casi" porque aunque los tipos de error deberían derivarse de Exception, eso no es forzoso.) –

+0

que no sería una mejor práctica, me imagino que – SilentGhost

+0

Sí, debe atrapar errores específicos. Y recuerda que es mejor pedir perdón que pedir permiso. Así que prefiero intentar ... excepto en lugar de if-you-can ... else-error-message. – mk12

0

Cuando Python se ejecuta en una condición de error, está arrojando una excepción.

La forma de manejar esto es atrapar la excepción y quizás manejarla.

Puede consultar la sección sobre excepciones en el pitón tutorial.

Usted expresó un interés en atrapar todas las excepciones. Esto podría hacerse capturando la clase Excepción. de acuerdo con la documentación:

Todo incorporado, no es del sistema-salir excepciones son derivado de esta clase . Todas las excepciones definidas por el usuario también deben derivarse de esta clase

2

todos los errores posibles

las otras respuestas más o menos cubierta de cómo hacer que su programa de forma normal fallar, pero me gustaría mencionar una cosa - usted no desea gracia fallar todos los errores. Si oculta todos sus errores, no se mostrarán los que indican que la lógica del programa es incorrecta, es decir, los errores que desea que vea.

Por lo tanto, si bien es importante conocer sus excepciones, asegúrese de saber exactamente qué excepciones están siendo detectadas.

Cuestiones relacionadas