Manejo de excepciones

sys incluye características para atrapar y trabajar con excepciones.

Excepciones no manejadas

Muchas aplicaciones están estructuradas con un bucle principal que envuelve la ejecución en un controlador de excepción global para atrapar errores que no se manejan en un nivel inferior. Otra forma de lograr lo mismo es estableciendo sys.excepthook en una función que tome tres argumentos (el tipo de error, el valor de error y el rastreo) y permita que se ocupe de los errores no controlados.

sys_excepthook.py
import sys


def my_excepthook(type, value, traceback):
    print('Unhandled error:', type, value)


sys.excepthook = my_excepthook

print('Before exception')

raise RuntimeError('This is the error message')

print('After exception')

Dado que no hay un bloque try:except alrededor de la línea donde se genera la excepción, la siguiente llamada a print() no se ejecuta, aunque el gancho except esté establecido.

$ python3 sys_excepthook.py

Before exception
Unhandled error: <class 'RuntimeError'> This is the error
message

Excepción Actual

Hay momentos en los que se prefiere un controlador de excepción explícito, ya sea por claridad de código o para evitar conflictos con las bibliotecas que intentan instalar su propio excepthook. En estos casos, se puede crear una función de controlador común que no necesita que se le pase el objeto de excepción explícitamente llamando a exc_info() para recuperar la excepción actual para un hilo.

El valor de retorno de exc_info() es una tupla de tres miembros que contiene la clase de excepción, una instancia de excepción y un rastreo. Se prefiere usar exc_info() sobre la forma anterior (con exc_type, exc_value y exc_traceback) porque es seguro para subprocesos.

sys_exc_info.py
import sys
import threading
import time


def do_something_with_exception():
    exc_type, exc_value = sys.exc_info()[:2]
    print('Handling {} exception with message "{}" in {}'.format(
        exc_type.__name__, exc_value,
        threading.current_thread().name))


def cause_exception(delay):
    time.sleep(delay)
    raise RuntimeError('This is the error message')


def thread_target(delay):
    try:
        cause_exception(delay)
    except RuntimeError:
        do_something_with_exception()


threads = [
    threading.Thread(target=thread_target, args=(0.3,)),
    threading.Thread(target=thread_target, args=(0.1,)),
]

for t in threads:
    t.start()
for t in threads:
    t.join()

Este ejemplo evita la introducción de una referencia circular entre el objeto de rastreo y una variable local en el marco actual al ignorar esa parte del valor de retorno de exc_info(). Si se necesita el rastreo (por ejemplo, para que se pueda registrar), elimina explícitamente la variable local (usando del) para evitar ciclos.

$ python3 sys_exc_info.py

Handling RuntimeError exception with message "This is the error
message" in Thread-2
Handling RuntimeError exception with message "This is the error
message" in Thread-1

Excepción interactiva anterior

En el intérprete interactivo, solo hay un hilo de interacción. Las excepciones no controladas en ese hilo se guardan en tres variables en sys (last_type, last_value y last_traceback) para que sea fácil recuperarlas para la depuración. El uso del depurador post mortem en pdb evita cualquier necesidad de usar los valores directamente.

$ python3
Python 3.4.2 (v3.4.2:ab2c023a9432, Oct  5 2014, 20:42:22)
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> def cause_exception():
...     raise RuntimeError('This is the error message')
...
>>> cause_exception()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in cause_exception
RuntimeError: This is the error message
>>> import pdb
>>> pdb.pm()
> <stdin>(2)cause_exception()
(Pdb) where
  <stdin>(1)<module>()
> <stdin>(2)cause_exception()
(Pdb)

Ver también

  • exceptions – Errores incorporados
  • pdb – Depurador Python
  • traceback – Módulo para trabajar con rastreos