Python 3: es excepcional

sábado, 27 de diciembre de 2008
El manejo de excepciones en Python 3 recibió también un cambio menor, pero que tiene por objeto evitar una fuente muy común de bugs en el código producidos por el descuido del programador.

Lanzando

En Python 2.x, la sintaxis para lanzar una excepción era usualmente la siguiente:
raise ValueError, "Error de valor!" # o bien
raise ValueError("Error de valor!")
Sin embargo, existe una cantidad de casos diferentes y poco conocidos que se detallan en un largo párrafo del manual de referencia. Está claro que esto es poco deseable, puesto que introduce complicaciones en el lenguaje con el objeto de facilitar usos poco comunes.

Volviendo al caso "usual" citado antes, si bien ambos casos eran equivalentes, se decidió eliminar el primero puesto que la sintaxis resulta un poco confusa. Al leer, no se entiende fácilmente que en realidad el argumento que viene después de la coma en el raise se pasa al constructor de la excepción. Por lo tanto, de ahora en más habrá que restringirse a la segunda opción:
raise ValueError("Error de valor!")
Atajando

Del mismo modo, para atrapar una excepción, se utilizaba el siguiente bloque:
try:
    ... # codigo que lanza una excepción
except ValueError:
    ... # codigo que maneja la excepción
Ahora, si se desea observar el contenido de la excepción para manipularlo de alguna manera, se utiliza el siguiente bloque except:
except ValueError, e:
    print e # "e" referencia la excepción
La dificultad en este caso proviene del uso de la variable e, que puede fácilmente confundirse en el contexto siguiente:
try:
    ... # codigo que lanza una excepción
except (ValueError, TypeError):
    print e
Como se observa, la idea del código es atrapar una excepción de cualquiera de los dos tipos especificados. Sin embargo, muchas veces en las que se desea hacer esto, se termina escribiendo:
except ValueError, TypeError:
    ... # TypeError es ahora una ref. a la excepción!
Está claro que el comportamiento no es el esperado: el bloque citado no atrapa las excepciones de tipo TypeError, sino que únicamente presta atención a los ValueError.

Para evitar esta situación, se introduce a partir de Python 3 una nueva sintaxis que reutiliza el keyword as, ya utilizado antes con las inclusiones de módulos externos para establecer un nombre diferente al módulo importado. La nueva sintaxis se ve así:
except (ValueError, TypeError) as e:
    ... # "e" es lo que uno espera
Gracias a estos cambios se eliminan varias ambiguedades y semánticas complicadas en pos de la simplicidad. Con cambios como estos se hace que el código sea más legible para quienes son nuevos con el lenguaje, y se evitan bugs difíciles de detectar en el manejo de excepciones.

1 comentario:

Pablo Antonio dijo...

Se extrañaban ya los posts sobre Python 3K :)

Sobre los cambios, en este caso no hay demasiado para decir más que comentar que me parecen acertados. La nueva sintaxis es mucho más entendible, y lo de crear una excepción usando una sintaxis diferente a la típica para instanciar objetos no tenía sentido.

Publicar un comentario