() translation by (you can also view the original English article)
En desarrollo de software, diferentes tipos de errores pueden ocurrir. Podrían ser errores de sintaxis, errores lógicos o errores de tiempo de ejecución.
Los errores de sintaxis es más probable que ocurran durante la fase de desarrollo inicial y son el resultado de sintaxis incorrecta. Los errores de sintaxis pueden ser atrapados fácilmente cuando se compila el programa para su ejecución.
Los errores lógicos, por otra parte, son el resultado de una incorrecta implementación lógica. Un ejemplo sería un programa accediendo a una lista no ordenada suponiendo que lo estuviera. Los errores lógicos son los más difíciles de rastrear.
Los errores de tiempo de ejecución son los errores que ocurren más interesantes, si no consideramos todos los casos posibles. Un ejemplo sería tratar de acceder a un archivo inexistente.
En este tutorial, aprenderemos cómo manejar errores en Python y cómo registrar los errores para una mejor comprensión de lo que pasó dentro de la aplicación.
Manejando Excepciones en Python
Vamos a empezar con un sencillo programa para sumar dos números en Python. Nuestro programa toma dos parámetros como entrada e imprime la suma. Aquí está un programa en Python para sumar dos números:
1 |
def addNumbers(a, b): |
2 |
print a + b |
3 |
|
4 |
addNumbers(5, 10) |
Intenta ejecutar el programa anterior de Python, y deberías de obtener la suma impresa.
1 |
15 |
Al escribir el programa anterior, realmente no consideramos el hecho de que algo pudiera salir mal. ¿Qué pasaría si uno de los parámetros pasados no es un número?
1 |
addNumbers('', 10) |
No hemos manejado ese caso, por lo tanto, nuestro programa se va a romper con el siguiente mensaje de error:
1 |
Traceback (most recent call last): |
2 |
File "addNumber.py", line 4, in <module> |
3 |
addNumbers('', 10) |
4 |
File "addNumber.py", line 2, in addNumbers |
5 |
print a + b |
6 |
TypeError: cannot concatenate 'str' and 'int' objects |
Podemos manejar la cuestión anterior comprobando si los parámetros pasados son números enteros. Pero eso no soluciona el problema. ¿Qué pasa si el código se rompe por alguna otra razón y causa que el programa se bloquee? Trabajar con un programa que se rompe al encontrarse con un error no es da una buena vista. Incluso si se ha producido un error desconocido, el código debe ser lo suficientemente robusto como para manejar la ruptura con gracia y que el usuario sepa que algo está mal.
Manejo de Excepciones Usando Try y Except
En Python, utilizamos las declaraciones try
y except
para controlar excepciones. Cuando el código se rompe, se produce una excepción sin que se caiga el programa. Vamos a modificar el programa que agrega números para incluir las declaraciones try
y except
.
1 |
def addNumbers(a, b): |
2 |
try: |
3 |
return a + b |
4 |
except Exception as e: |
5 |
return 'Error occurred : ' + str(e) |
6 |
|
7 |
print addNumbers('', 10) |
Python procesaría todo el código dentro de las declaraciones try
y except
. Cuando encuentra un error, el control se pasa al bloque except
, omitiendo el código en el medio.
Como se ve en el código anterior, nos hemos trasladado nuestro código dentro de una declaración try
y except
. Intenta ejecutar el programa y debe lanzar un mensaje de error en lugar de que se caiga el programa. También, el motivo de la excepción se devuelve como un mensaje de excepción.
El método anterior maneja las excepciones inesperadas. Echemos un vistazo a cómo manejar una excepción prevista. Asume que estamos tratando de leer un archivo con nuestro programa de Python, pero el archivo no existe. En este caso, controlaremos la excepción y permitiremos al usuario saber que el archivo no existe cuando ocurra. Echa un vistazo al código de lectura de archivo:
1 |
try: |
2 |
try: |
3 |
with open('fname') as f: |
4 |
content = f.readlines() |
5 |
except IOError as e: |
6 |
print str(e) |
7 |
except Exception as e: |
8 |
print str(e) |
En el código anterior, hemos manejado la lectura de archivo dentro de un controlador de excepción IOError
. Si el código se rompe debido a la falta de disponibilidad del archivo fname
, el error sería manejado dentro del controlador IOError
. Similar a la excepción IOError
, hay excepciones mucho más estándar como Arithmetic
, OverflowError
e ImportError
, por nombrar unos pocos.
Múltiples Excepciones
Podemos manejar excepciones múltiples a la vez juntando las excepciones estándar como se muestra:
1 |
try: |
2 |
with open('fname') as f: |
3 |
content = f.readlines() |
4 |
printb
|
5 |
except (IOError,NameError) as e: |
6 |
print str(e) |
El código anterior mostraría las excepciones IOError
y NameError
cuando se ejecute el programa.
Clausula finally
Supongamos que estamos utilizando ciertos recursos en nuestro programa de Python. Durante la ejecución del programa, se encontró un error y sólo se ejecutó a medias. En este caso, el recurso será mantenido innecesariamente. Podemos limpiar tales recursos mediante la cláusula finally
. Echa un vistazo al siguiente código:
1 |
try: |
2 |
filePointer = open('fname','r') |
3 |
try: |
4 |
content = filePointer.readline() |
5 |
finally: |
6 |
filePointer.close() |
7 |
except IOError as e: |
8 |
print str(e) |
Si durante la ejecución del código anterior, se produce una excepción al leer el archivo, filePointer
sería cerrado en el bloque finally
.
Registros en Python
Cuando algo va mal dentro de una aplicación, es más fácil depurar si conocemos la fuente del error. Cuando se produce una excepción, podemos registrar la información necesaria para localizar el problema. Python proporciona una biblioteca de registro simple y potente. Vamos a echar un vistazo a cómo utilizar registros en Python.
1 |
import logging |
2 |
|
3 |
# initialize the log settings
|
4 |
logging.basicConfig(filename='app.log',level=logging.INFO) |
5 |
|
6 |
try: |
7 |
logging.info('Trying to open the file') |
8 |
filePointer = open('appFile','r') |
9 |
try: |
10 |
logging.info('Trying to read the file content') |
11 |
content = filePointer.readline() |
12 |
finally: |
13 |
filePointer.close() |
14 |
except IOError as e: |
15 |
logging.error('Error occurred ' + str(e)) |
Como se ve en el código anterior, primero tenemos que importar la biblioteca de registro de Python y luego inicializar el registrador con el nombre del archivo de registro y nivel de registro. Hay cinco niveles de registro: DEBUG, INFO, WARNING, ERROR y CRITICAL. Aquí tenemos que ajustar el nivel de registro a INFO, por lo tanto, INFO y los registros anteriores se registrarán.
Consiguiendo el Seguimiento de Pila
En el código anterior tuvimos un archivo de programa, por lo tanto era más fácil de averiguar dónde había ocurrido el error. Pero ¿qué hacemos cuando se trata de varios archivos de programa? En tal caso, conseguir la pila de errores ayuda en la búsqueda de la fuente del error. El seguimiento de pila de la excepción puede haberse registrado como se muestra:
1 |
import logging |
2 |
|
3 |
# initialize the log settings
|
4 |
logging.basicConfig(filename = 'app.log', level = logging.INFO) |
5 |
|
6 |
try: |
7 |
filePointer = open('appFile','r') |
8 |
try: |
9 |
content = filePointer.readline() |
10 |
finally: |
11 |
filePointer.close() |
12 |
except IOError as e: |
13 |
logging.exception(str(e)) |
Si intentas ejecutar el programa anterior, al surgir una excepción el siguiente error se registra en el archivo de registro:
1 |
ERROR:root:[Errno 2] No such file or directory: 'appFile' |
2 |
Traceback (most recent call last): |
3 |
File "readFile.py", line 7, in <module> |
4 |
filePointer = open('appFile','r') |
5 |
IOError: [Errno 2] No such file or directory: 'appFile' |
En Resumen
En este tutorial, vimos cómo empezar con el manejo de errores de Python y la utilización del módulo de registro para registrar errores. Vimos el uso de las declaraciones try
, except
y finally
, que son muy útiles cuando se manejan errores en Python. Para obtener más información, recomiendo leer la documentación oficial sobre registros. También echa un vistazo a la documentación para manejar excepciones en Python.
Haznos saber tus ideas en los comentarios abajo.