Curso de Python: 9-Control de excepciones

Durante la ejecución de un código, pueden ocurrir hechos que provoquen un error, tales como acceder a un fichero que no existe, escribir en un fichero protegido contra escritura, dividir un número entre cero, etc. Python permite ejercer un control sobre estos errores declarando excepciones, y evitar que la ejecución se detenga. Veamos un ejemplo muy sencillo:

>>> def division(a,b):
...    return a/b
...
>>> division(2,0)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in division
ZeroDivisionError: integer division or modulo by zero

El intérprete de Python, al intentar dividir entre 0, produce un error fatal, informando del punto en que se ha producido. Si fuera un programa, éste se detendría en el punto del error, y el intérprete de Python mostraría la jerarquía de llamadas de funciones hasta el módulo, la función y la línea donde se produjo el error. Para evitar que el programa se detenga, se trata el error dentro de un bloque de excepción:

>>> def division(a,b): 
...    try:
...       return a/b
...    except: # Tratamiento de excepcion
...       return 0
...
>>> division(6,3)
2
>>> division(5,0)
0

El bloque try contiene el código que al ejecutarse podría producir alguna excepción. En caso de producirse, la ejecución saltará al bloque de código definido por except.

En el ejemplo anterior se ha tratado una excepción genérica, pero es posible tratar una o varias excepciones concretas, indicando el tipo de excepción en la declaración except:

>>> def division(a,b):
...    return a/b
...
>>> try:
...    num1=int(raw_input("Dame dividendo:"))
...    num2=int(raw_input("Dame divisor:"))
...    print num1,'/',num2,'=',division(num1,num2)
... except ValueError:
...    print 'El valor introducido no es un numero entero'
... except ZeroDivisionError:
...    print 'No se puede dividir entre cero'
...
Dame dividendo:20e
El valor introducido no es un numero entero

Dame dividendo:45
Dame divisor:0
45 / 0 = No se puede dividir entre cero

Es posible tratar varias excepciones en un mismo bloque except:

... except (ValueError, ZeroDivisionError, TypeError...):
...    # Bloque a ejecutar

Para extraer la información de una excepción, se asigna ésta a una variable para después acceder a sus
propiedades:

>>> try: 
...    a = division(30,0)
... except Exception as info:
...    print type(info)
...    print info.args
...    print info
...
<type 'exceptions.ZeroDivisionError'>
('integer division or modulo by zero',)
integer division or modulo by zero

En un código controlado, es posible crear o lanzar nuestras propias excepciones a través de la declaración raise, la cual toma, al menos un parámetro:

>>> try:
...    # Codigo para lanzar una excepcion propia
...    raise Exception('Error de admisión', 'Error número 39')
... except Exception as infoex:
...    print type(infoex) # Tipo
...    print infoex.args # Argumentos
...    print infoex # __str__ Muestra argumentos
...    arg1, arg2 = infoex # __getitem__ Extrae argumentos
...    print “arg1 =”,arg1 # Muestra argumento 1
...    print “arg2 =”,arg2 # Muestra argumento 2
...
<type 'exceptions.Exception'>
('Error de admision', 'Error numero 39')
('Error de admision', 'Error numero 39')
arg1 = Error de admision
arg2 = Error numero 39

Para llevar un mejor control de nuestras excepciones, podemos crear una clase específica para ser reutilizada en nuestros programas:

>>> class MiExcepcion(Exception):
...    def __init__(self,valor):
...       self.valor = valor
...    def __str__(self):
...       return repr(self.valor)
...
>>> try:
...    raise MiExcepcion("Admision erronea")
... except MiExcepcion as e:
...    print "Error: ", e.valor
...
Error: Admision erronea



Entregas:

Enlaces de interés: