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())
entonces, ¿cómo obtengo un trackback en los registros? – FurtiveFelon
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