Artículo original escrito por Bala Priya C
Artículo original Python Try and Except Statements – How to Handle Exceptions in Python
Traducido y adaptado por Franciscomelov

Al programar en Python algunas veces podemos anticipar errores de ejecución, incluso en un programa sintáctica y lógicamente correcto, pueden llegar a haber errores causados por entrada de datos inválidos o inconsistencias predecibles.

En Python, puedes usar los bloques try y except para manejar estos errores como excepciones.

En este tutorial aprenderás la sintaxis básica de try y except. Después escribirás ejemplos simples, detectaras que puede salir mal y brindaras soluciones correctivas usando los bloques try y except.

Sintaxis de Try y Except en Python

Empecemos por entender la sintaxis de las declaraciones try y except en Python. La sintaxis básica es la siguiente:

try:
	# Codigo a ejecutar
	# Pero podria haber errores en este bloque
    
except <tipo de error>:
	# Haz esto para manejar la excepcion
	# El bloque except se ejecutara si el bloque try lanza un error
    
else:
	# Esto se ejecutara si el bloque try se ejecuta sin errores
   
finally:
	# Este bloque se ejecutara siempre

Veamos el uso de cada uno de estos bloques:

  • EL bloque try es el bloque con las sentencias que quieres ejecutar. Sin embargo, podrían llegar a haber errores de ejecución  y el bloque se dejará de ejecutarse.
  • El bloque except se ejecutará cuando el bloque try falle debido a un error. Este bloque contiene sentencias que generalmente nos dan un contexto de lo que salió mal en el bloque try.
  • Siempre deberías de mencionar el tipo de error que se espera, como una excepción dentro del bloque except dentro de <tipo de error> como lo muestra el ejemplo anterior.
  • Podrías usar except sin especificar el <tipo de error>. Pero no es una práctica recomendable, ya que no estarás al tanto de los tipos de errores que puedan ocurrir.
Cuando se ejecute el código dentro del bloque try, existe la posibilidad de que ocurran diferentes errores.

Por ejemplo, podrías acceder a una lista utilizando un índice fuera de rango, usar una clave incorrecta en un diccionario y tratar de abrir un archivo que no existe - todo esto dentro de un bloque try.

En este caso, podrías esperar lo siguiente: IndexError, KeyError y FileNotFoundError. Y tendrías que añadir un bloque except por cada tipo de error que puedas anticipar.

  • El bloque else se ejecutará solo si el bloque try se ejecuta sin errores. Esto puede ser útil cuando quieras continuar el código del bloque try. Por ejemplo si abres un archivo en el bloque try, podrías leer su contenido dentro del bloque else.
  • El bloque finally siempre es ejecutado sin importar que pase en los otros bloques, esto puede ser útil cuando quieras liberar recursos después de la ejecución de un bloque de código,  ( try, except o else ).
Nota: Los bloques else y finally son opcionales. En muchos casos puedes solo ocupar el bloque try para tratar de ejecutar algo y capturar los errores como excepciones  en el bloque except.

Ahora es momento de usar lo que has aprendido sobre el manejo de excepciones en Python.
Empecemos.

Como manejar ZeroDivisionError en Python

Considera la siguiente función, dividir(), toma 2 argumentos - num y div - y retorna el resultado o cociente de dividir num/ div.

def dividir(num,div):
  return num/div

▶ Llamar a la función con diferentes números retorna el resultado de la división.

res = dividir(100,8)
print(res)

# Salida
12.5

res = dividir(568,64)
print(res)

# Salida
8.875

Este código funciona hasta que tratamos de dividir entre cero:

dividir(27,0)

Puedes ver que el programa se detiene y arroja ZeroDivisionError:

# Salida
---------------------------------------------------------------------------
ZeroDivisionError                         Traceback (most recent call last)
<ipython-input-19-932ea024ce43> in <module>()
----> 1 dividir(27,0)

<ipython-input-1-c98670fd7a12> in dividir(num, div)
      1 def divide(num,div):
----> 2   return num/div

ZeroDivisionError: division by zero
ZeroDivisionError
Esta linea nos describe el tipo de error y se podria traducir como:

"Error de division entre cero"

Y lo vemos cuando en python intentamos dividir un numero entre cero

Podemos tratar esta división entre cero como una excepción, haciendo lo siguiente:

  • Desde el bloque try llama a la función dividir().
  • En el bloque except tendremos una excepción en caso de que div sea igual a cero.
  • En este ejemplo se hace una excepción a ZeroDivisionError (el tipo de error) el cual se especifica en except
  • Cuando se detecte el error ZeroDivisionError se ejecutara el bloque except donde pondremos un mensaje informando que se trató de dividir entre cero.

Aquí se muestra el código completo:

try:
    res = dividir(num, div)
    print(res)
except ZeroDivisionError:
    print("Trataste de dividir entre cero :( ")

Con una entrada valida el código funciona correctamente:

dividir(10,2)
# Salida
5.0

Cuando tratas de dividir entre cero, se notificara de la excepción  y el código seguirá ejecutándose.

dividir(10,0)
# Salida
Trataste de dividir entre cero :(

Como enfrentar TypeError en  Python

En esta sección, verás como usar try y except para manejar el error TypeError en Python.

▶Piensa en una función llamada  mas_10(), que toma un número como argumento, le añade 10, y retorna el resultado de la suma.

def mas_10(num):
  return num + 10

Puedes llamar a la función mas_10() con cualquier número y funcionará correctamente, como puedes ver en el siguiente ejemplo:

resultado = mas_10(89)
print(resultado)

# Salida
99

Ahora trata llamar a mas_10() con "cinco" en lugar de 5.

add_10("cinco")

Notarás que tu programa se detiene y el siguiente mensaje de error es mostrado.

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-15-9844e949c84e> in <module>()
----> 1 add_10("five")

<ipython-input-13-2e506d74d919> in add_10(num)
      1 def add_10(num):
----> 2   return num + 10

TypeError: can only concatenate str (not "int") to str
TypeError
Este error se puede traducir como:
"Error de tipo" 
Que sale cuando usamos un tipo de dato incorrecto.

can only concatenate str (not "int") to str
Esta linea se puede traducir como:
Solo se puede concatenar una cadenas de texto, (no un "numero entero") a otra cadena de texto.

Ya que no se pueden hacer operaciones entre un numero y un texto.

Ahora, teniendo el siguiente código:

mi_num = "cinco"
try:
  resultado = mas_10(mi_num)
  print(resultado)
except TypeError:
  print("El argumento `mi_num` deberia ser un número")

Así funciona el código anterior:

  • Teniendo la variable mi_num, llamamos a la función mas_10() con mi_num como argumento, si el argumento es un tipo de dato válido, no se activará la excepción.
  • De lo contrario, el bloque except con el tipo de error TypeError se activará,  notificándole al usuario que el argumento es un tipo de dato inválido.
# Salida

El argumento `mi_num` deberia ser un número

Ya que estamos especificando que TypeError es una excepción el programa no se detendrá y te notificara que el argumento es inválido.

Como manejar IndexError en Python

Si has trabajado con listas en Python o cualquier tipo de iterable, probablemente ya hayas visto el error IndexError.

Esto ocurre, ya que a veces es difícil estar al tanto de todos los cambios en un iterable y podrías estar usando un índice no válido para acceder a un elemento del iterable.

mira la siguiente lista:

mi_lista = ["Python","C","C++","JavaScript"]

▶ En este ejemplo, mi_lista tiene 4 elementos. Los índices válidos son 0, 1, 2, 3  y -1, -2, -3, -4 si usas indexación negativa.

mi_lista = ["Python","C","C++","JavaScript"]
print(my_lista[2])

# Salida
C++

Ya que 2es un índice válido, al imprimir my_lista[2] el elemento c++ es mostrado en pantalla.

Si tratas de acceder a la lista con un índice fuera del rango permitido, ocurrirá un error en la ejecución y aparecerá el error IndexError:

print(mi_lista[4])
---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
<ipython-input-7-437bc6501dea> in <module>()
      1 mi_lista = ["Python","C","C++","JavaScript"]
----> 2 print(mi_lista[4])

IndexError: list index out of range
IndexError
Esta linea se puede traducir como:
Error de indice

list index out of range
Esta linea se puede traducir como:
indice de la lista fuera de rango

Si ya te familiarizaste  con los bloques try y except sabes que podemos usarlos para evitar el error anterior.

▶En el siguiente código, etas intentando acceder a un elemento con la variable buscar_ind

mi_lista = ["Python","C","C++","JavaScript"]
buscar_ind = 3
try:
  print(mi_lista[buscar_ind])
except IndexError:
  print("Lo siento, el indice esta fuera de rango")

Aquí, buscar_ind  (3) es un índice válido, y elemento en ese índice  es impreso en pantalla:

JavaScript

Si buscar_ind está fuera del rango permitido, el bloque except reconoce el error IndexError como una excepcion y se mostrara nuestro pequeño mensaje en lugar de la descripción larga del error  ?.

mi_lista = ["Python","C","C++","JavaScript"]
buscar_ind = 4
try:
  print(mi_lista[buscar_ind])
except IndexError:
  print("Lo siento, el indice esta fuera de rango")

Aquí podemos ver nuestro mensaje personalizado para la excepción

Lo siento, el indice esta fuera de rango

Como manejar KeyError en Python

Si has trabajado con diccionarios en Python, probablemente el error  keyError no sea algo nuevo.

▶ Examina el siguiente código donde tenemos un diccionario mi_dict.

mi_dict ={"clave1":"valor1", "clave2":"valor2", "clave3":"valor3"}
buscar_clave = "clave no existente"
print(mi_dict[buscar_clave])
  • El diccionario mi_dict tiene 3 pares "clave-valor", "clave1":"valor1", "clave2":"valor2", "clave3":"valor3"
  • Intentamos acceder a los valores del diccionario con la clave "clave no existente".

Ya que la clave no existe, el programa se detiene y obtenemos el error keyError.

---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
<ipython-input-2-2a61d404be04> in <module>()
      1 my_dict ={"key1":"value1","key2":"value2","key3":"value3"}
      2 search_key = "non-existent key"
----> 3 my_dict[search_key]

KeyError: 'non-existent key'
KeyError
Este la linea se puede traducir como:
Error de clave

'non-existent key'
Esta linea se puede traducir como:
Clave no existente

Puedes resolver el error KeyError de la misma forma que el error anterior IndexError.

try:
  print(mi_dict[buscar_clave])
except KeyError:
  print("¡Lo siento, clave invalida!")
  • Accedemos al diccionario con una clave especificada en buscar_clave
  • Si buscar_clave contiene una clave válida, el valor correspondiente será impreso en pantalla.
  • Si, por el contrario, la clave no existe, usamos el bloque except para tratar al error keyError como una excepción e informar al usuario con un pequeño mensaje.
¡Lo siento, clave invalida!

▶ También es posible añadir información extra; como el nombre de la clave inválida, talvez solo ingresaste mal la clave, lo que provocaría el error, hacerle saber al usuario la clave que introdujo podría ayudarle a corregir errores de escritura, como escribir nombe en lugar de nombre.

Puedes hacerlo guardando la clave inválida en <msg_error> y agregarla en nuestro mensaje de error.

try:
  print(mi_dict[buscar_clave])
except KeyError as msg_error::
  print(f"¡Lo siento, {error_msg} no es una clave valida!")

▶Puedes ver como el nombre de la clave también se imprime en pantalla:

¡Lo siento, 'clave no existente' no es una clave valida!

Como manejar  FileNotFoundError en Python

Un error común al trabajar con archivos en Python es el error FileNotFoundError.

▶En el siguiente ejemplo, trataras de abrir el archivo mi_archivo.txt especificando su ruta en la función open(), después intentaras leerlo e imprimir su contenido.

Sin embargo, aún no has creado el archivo en la ruta especificada.

Si intentas correr el código siguiente, obtendrás el error FileNotFoundError:

mi_archivo = open("Contenido/datos_muestra/mi_archivo.txt")
contenido = mi_archivo.read()
print(contenido)
---------------------------------------------------------------------------
FileNotFoundError                         Traceback (most recent call last)
<ipython-input-4-4873cac1b11a> in <module>()
----> 1 my_file = open("my_file.txt")

FileNotFoundError: [Errno 2] No such file or directory: 'my_file.txt'
FileNotFoundError
Esta linea se puede traducir como:
error, archivo no encontrado

No such file or directory: 'mi_archivo.txt.txt'
Esta linea se puede traducir como:
El archivo o directorio no existe: 'mi_archivo.txt.txt'

Usando try y except, puedes hacer lo siguiente:

  • Tratar de abrir el archivo en el bloque try.
  • En el bloque except tendremos una excepción en caso de que el archivo no exista y le notificaremos al usuario.
  • Si el bloque try no tiene errores y el archivo si existe, leeremos e imprimiremos el contenido del archivo.
  • En el bloque finally, cerramos el archivo para evitar desperdiciar recursos. Recuerda que el archivo será cerrado independientemente de lo que ocurra en los pasos de apertura y lectura del archivo
try:
  mi_archivo = open("Contenido/datos_muestra/mi_archivo.txt")
except FileNotFoundError:
  print(f"Lo siento, el archivo no existe")
else:
  contenido = mi_archivo.read()
  print(contenido)
finally:
  mi_archivo.close()


Ahora manejamos el error como una excepción y el programa termina solo con un pequeño mensaje:

Lo siento, el archivo no existe

▶ Ahora consideremos que el archivo mi_archivo.txt existe y, por lo tanto, el bloque else ya se podría ejecutar.

image-77

Y aquí está el contenido de miarchivo.txt:

image-7

Ahora que tenemos el archivo y carpetas, ejecutaremos una vez más el código anterior y debería funcionar sin problemas.

Esta vez, el archivo mi_archivo.txt está presente, el bloque else es ejecutado y su contenido es mostrado en pantalla.

Sin-t-tulo

Espero esto te haya dejado claro como manejar las excepciones cuando trabajes con archivos.

Conclusión

Este tutorial aprendiste como usar try y except en Python para manejar excepciones.

Escribiste ejemplos para entender que tipo de excepciones pueden ocurrir y como usar  except para detectar los errores más comunes.

Espero hayas disfrutado este tutorial.
Hasta la próxima :)