() translation by (you can also view the original English article)
Es muy común encontrar errores durante la ejecución de un programa. Dos tipos comunes de errores con los que podrías lidiar son errores de sintaxis y excepciones. Los errores de sintaxis ocurren cuando tecleas el código incorrectamente. En tales casos, la línea errónea es repetida por el analizador con una flecha apuntando a la primera ubicación en donde el error fue detectado.
Las excepciones son diferentes de los errores de sintaxis. Estos ocurren durante la ejecución de un programa cuando algo inesperado sucede. Por ejemplo, digamos que estás pidiendo al usuario que ingrese un número para poder realizar una división. Ahora, si el usuario ingresa una cadena en lugar de un número y trata de dividir un número entre la entrada dada, el programa mostrará un TypeError
.
Cuando no estás manejando excepciones apropiadamente, el programa se cerrará de manera abrupta ya que no sabe que hacer en tales casos. El siguiente caso es un ejemplo:
1 |
keep_asking = True |
2 |
|
3 |
while keep_asking: |
4 |
x = int(input("Enter a number: ")) |
5 |
print("Dividing 50 by", x,"will give you :", 50/x) |
Mientras estés ingresando un valor entero de entrada, el programa funcionará correctamente. Sin embargo, tan pronto como ingreses una cadena o incluso un número decimal como entrada, obtendrás una excepción ValueError
.
En este tutorial, aprenderás cómo manejar y levantar excepciones apropiadamente en Python.
Algunas Excepciones Comunes
Aquí hay algunas excepciones básicas que podrías encontrar cuando escribes programas. Puedes leer sobre más excepciones integradas en el sitio web oficial.
- NameError: Esta excepción es levantada cuando el programa no puede encontrar un nombre local o global. El nombre que podría no ser encontrado está incluido en el mensaje de error.
- TypeError: Esta excepción es levantada cuando una función se le pasa un objeto del tipo inapropiado como su argumento. Más detalles sobre el tipo incorrecto son proporcionados en el mensaje de error.
- ValueError: Esta excepción ocurre cuando un argumento de función tiene el tipo correcto pero un valor inapropiado.
- NotImplementedError: Esta excepción es levantada cuando se supone que un objeto apoye una operación pero no ha sido implementado aún. No deberías usar este error cuando la función dada no deba apoyar al tipo de argumento de entrada. En esas situaciones, levantar una excepción
TypeError
es más apropiado. - ZeroDivisionError: Esta excepción es levantada cuando proporcionas el segundo argumento para una operación de división o módulo como cero.
- FileNotFoundError: Esta excepción es levantada cuando el archivo o diccionario que el programa solicitó no existe.
Justo como los nombres de arriba, la mayoría de las excepciones tienen nombres que se explican por sí solos.
Manejando una Excepción
El código al inicio del artículo pedía a los usuarios ingresar un entero como entrada. Si el usuario no proporciona un valor entero, el programa detenía la ejecución y levantaba un valor de excepción de error. En esta sección, escribiremos algún código para decirle al usuario que su entrada no es un valor entero válido.
El primer paso del proceso es incluir el código que crees que podría levantar una excepción dentro de la cláusula try
. El siguiente paso es usar la palabra clave except
para manejar la excepción que ocurrió en el código de arriba. El código modificado para la entrada del usuario lucirá así:
1 |
keep_asking = True |
2 |
|
3 |
while keep_asking: |
4 |
try: |
5 |
x = int(input("Please enter a number: ")) |
6 |
print("Dividing 50 by", x,"will give you :", 50/x) |
7 |
except ValueError: |
8 |
print("The input was not an integer. Please try again...") |
Lo que pasa aquí es que el programa intenta ejecutar el código dentro de la cláusula try
. Si no se levantó ninguna excepción, el programa omite la cláusula except
y el resto del código se ejecuta de manera normal. Si una excepción es levantada, el programa omite el código restante dentro de la cláusula try
y el tipo de excepción es emparejada con el nombre de excepción después de la palabra clave except
. En caso de una coincidencia, el código dentro de la cláusula except
es ejecutado primero, y después el resto del código después de la cláusula try
es ejecutado de manera normal.
Cuando ingresas un entero como entrada, el programa te da el resultado final de la división. Cuando se proporciona un valor no entero, el programa imprime un mensaje pidiéndote intentar ingresar un entero otra vez. Nota que esta vez, el programa no se cierra de manera abrupta cuando proporcionas algún valor inválido.
Puedes tener múltiples cláusulas except
para manejar diferentes excepciones. Por favor ten en mente que estos manejadores solo lidiarán con excepciones que ocurrieron en la cláusula try
correspondiente. No manejarán cualquier cualquier excepción levantada dentro de otros manejadores de excepción.
También puedes manejar múltiples excepciones usando una sola cláusula except
pasando estas excepciones a la cláusula como una tuple
.
1 |
except (ZeroDivisionError, ValueError, TypeError): |
2 |
print("Something has gone wrong..") |
3 |
# code to deal with the exception
|
Finalmente, también puedes dejar fuera el nombre de la excepción después de otra palabra clave except
. Esto generalmente no es recomendable ya que el código ahora estará atrapando todas las excepciones y manejándolas de la misma manera. Esto no es óptimo ya que estarás manejando una excepción TypeError
de la misma manera que hubieras manejado una excepción ZeroDivisionError
. Cuando se manejan excepciones, es mejor ser tan específico como sea posible y solo atrapar lo que puedes manejar.
Un posible uso de atrapar todas las excepciones es imprimir apropiadamente el error de excepción en pantalla como el siguiente código:
1 |
import math |
2 |
import sys |
3 |
|
4 |
try: |
5 |
result = math.factorial(2.4) |
6 |
except: |
7 |
print("Something Unexpected has happened.",sys.exc_info()[0]) |
8 |
else: |
9 |
print("The factorial is", result) |
Usando la Cláusula Else
También puedes usar una cláusula else
en una declaración try ... except
. La cláusula else
está hecha para contener código que necesita ser ejecutado si la cláusula try
no levantó ninguna excepción. Esto puede ser útil para asegurar que no agregas ningún código al bloque try
cuyas excepciones no pretendes atrapar. Una cosa que vale la pena mencionar es que si decides usar una cláusula else
, deberías incluirla después de todas las cláusulas except
pero antes del bloque finally
.
En nuestro caso, podríamos mover la línea que imprime el resultado de nuestra división dentro del bloque else
.
1 |
keep_asking = True |
2 |
|
3 |
while keep_asking: |
4 |
try: |
5 |
x = int(input("Please enter a number: ")) |
6 |
except ValueError: |
7 |
print("The input was not a valid integer. Please try again...") |
8 |
else: |
9 |
print("Dividing 50 by", x,"will give you :", 50/x) |
Limpiando Usando la Cláusula Finally
Digamos que has escrito algún código dentro del bloque try
que se supone realice una tarea utilizando una gran cantidad de recursos. Es importante liberar esos recursos de vuelta cuando terminas de usarlos. Esto puede ser logrado fácilmente usando la cláusula finally
.
El código dentro de la cláusula finally
siempre se ejecuta independientemente de si el bloque try
levantó una excepción. Puedes verificar esto ejecutando el siguiente código:
1 |
keep_asking = True |
2 |
|
3 |
while keep_asking: |
4 |
try: |
5 |
x = int(input("Please enter a number: ")) |
6 |
except ValueError: |
7 |
print("The input was not a valid integer. Please try again...") |
8 |
else: |
9 |
print("Dividing 50 by", x,"will give you :", 50/x) |
10 |
finally: |
11 |
print("Already did everything necessary.") |
Si cualquiera de las cláusulas except
que especificaste no maneja la excepción levantada, la misma excepción es levantada de nuevo después de la ejecución del código dentro del bloque finally
.
Un Ejemplo Más Complejo
En esta sección, escribiremos un programa para lidiar con múltiples excepciones. Justo como en los ejemplos anteriores, estaremos realizando algunas operaciones matemáticas. Sin embargo, esta vez tomaremos la entrada de una lista.
El siguiente código revisa dos excepciones, TypeError
y ValueError
. El bloque else
es usado para imprimir el factorial. Puedes ver en la salida que este código es ejecutado solo cuando no se levanta ninguna excepción.
1 |
import math |
2 |
|
3 |
number_list = [10,-5,1.2,'apple'] |
4 |
|
5 |
for number in number_list: |
6 |
try: |
7 |
number_factorial = math.factorial(number) |
8 |
except TypeError: |
9 |
print("Factorial is not supported for given input type.") |
10 |
except ValueError: |
11 |
print("Factorial only accepts positive integer values.", number," is not a positive integer.") |
12 |
else: |
13 |
print("The factorial of",number,"is", number_factorial) |
14 |
finally: |
15 |
print("Release any resources in use.") |
El código de arriba produce la siguiente salida:
1 |
The factorial of 10 is 3628800 |
2 |
Releasing any resources in use. |
3 |
|
4 |
Factorial only accepts positive integer values. -5 is not a positive integer. |
5 |
Releasing any resources in use. |
6 |
|
7 |
Factorial only accepts positive integer values. 1.2 is not a positive integer. |
8 |
Releasing any resources in use. |
9 |
|
10 |
Factorial is not supported for given input type. |
11 |
Releasing any resources in use. |
Otra cosa que vale la pena notar es que el código dentro de la cláusula finally
se ejecuta para cada elemento en la lista.
Ideas Finales
Espero que este tutorial te haya ayudado a entender el manejo de excepciones en Python. De manera adicional, no dudes en ver qué tenemos disponible a la venta y para estudiar en el marketplace, y no dudes en hacer preguntas y proporcionar tu valiosa retroalimentación usando la sección de abajo.
Manejar excepciones apropiadamente puede ser muy útil en situaciones en donde no es viable salir de un programa después de que este reciba una entrada inesperada. Si tienes cualquier pregunta relacionada con manejar una excepción en Python, por favor déjame saber en los comentarios.