¿Excepciones?¶
Desafío 1: analicemos este código¶
¿Dónde se puede producir una excepción? ¿Cuál o cuáles?
In [2]:
Copied!
mi_musica = {70: ["Stairway to heaven", "Bohemian Rhapsody"],
80: ["Dancing in the dark", "Welcome to the jungle", "Under pressure"],
2000:["Given up", "The pretender"]}
tema = input("Ingresá un nuevo tema (FIN para terminar): ")
while tema !="FIN":
decada = int(input("ingresá a qué década pertenece: "))
mi_musica[decada].append(tema)
tema = input("Ingresá un nuevo tema (FIN para terminar): ")
mi_musica = {70: ["Stairway to heaven", "Bohemian Rhapsody"],
80: ["Dancing in the dark", "Welcome to the jungle", "Under pressure"],
2000:["Given up", "The pretender"]}
tema = input("Ingresá un nuevo tema (FIN para terminar): ")
while tema !="FIN":
decada = int(input("ingresá a qué década pertenece: "))
mi_musica[decada].append(tema)
tema = input("Ingresá un nuevo tema (FIN para terminar): ")
Ingresá un nuevo tema (FIN para terminar): run ingresá a qué década pertenece: veinte
--------------------------------------------------------------------------- ValueError Traceback (most recent call last) Input In [2], in <cell line: 6>() 5 tema = input("Ingresá un nuevo tema (FIN para terminar): ") 6 while tema !="FIN": ----> 7 decada = int(input("ingresá a qué década pertenece: ")) 8 mi_musica[decada].append(tema) 10 tema = input("Ingresá un nuevo tema (FIN para terminar): ") ValueError: invalid literal for int() with base 10: 'veinte'
Recordemos: ¿qué es un excepción?¶
Una excepción es un acontecimiento, que ocurre durante la ejecución de un programa, que interrumpe el flujo normal de las instrucciones del programa.
In [3]:
Copied!
mi_musica = {70: ["Stairway to heaven", "Bohemian Rhapsody"],
80: ["Dancing in the dark", "Welcome to the jungle", "Under pressure"],
2000:["Given up", "The pretender"]}
tema = input("Ingresá un nuevo tema (FIN para terminar): ")
while tema !="FIN":
try:
decada = int(input("ingresá a qué década pertenece: "))
mi_musica[decada].append(tema)
except ValueError:
print("Para ingresar la decada, tenés que ingresar un número. Empecemos de nuevo...")
except KeyError:
print("""Por ahora, sólo tengo registradas las décadas: 70, 80 y 2000. Ingresá una de ellas.
Empecemos de nuevo...""")
tema = input("Ingresá un nuevo tema (FIN para terminar): ")
mi_musica = {70: ["Stairway to heaven", "Bohemian Rhapsody"],
80: ["Dancing in the dark", "Welcome to the jungle", "Under pressure"],
2000:["Given up", "The pretender"]}
tema = input("Ingresá un nuevo tema (FIN para terminar): ")
while tema !="FIN":
try:
decada = int(input("ingresá a qué década pertenece: "))
mi_musica[decada].append(tema)
except ValueError:
print("Para ingresar la decada, tenés que ingresar un número. Empecemos de nuevo...")
except KeyError:
print("""Por ahora, sólo tengo registradas las décadas: 70, 80 y 2000. Ingresá una de ellas.
Empecemos de nuevo...""")
tema = input("Ingresá un nuevo tema (FIN para terminar): ")
Ingresá un nuevo tema (FIN para terminar): Run ingresá a qué década pertenece: 2020 Por ahora, sólo tengo registradas las décadas: 70, 80 y 2000. Ingresá una de ellas. Empecemos de nuevo... Ingresá un nuevo tema (FIN para terminar): Ascenso ingresá a qué década pertenece: veinte Para ingresar la decada, tenés que ingresar un número. Empecemos de nuevo... Ingresá un nuevo tema (FIN para terminar): FIN
Podríamos haber manejado de ambas excepciones juntas:¶
In [4]:
Copied!
mi_musica = {70: ["Stairway to heaven", "Bohemian Rhapsody"],
80: ["Dancing in the dark", "Welcome to the jungle", "Under pressure"],
2000:["Given up", "The pretender"]}
tema = input("Ingresá un nuevo tema (FIN para terminar): ")
while tema !="FIN":
try:
decada = int(input("ingresá a qué década pertenece: "))
mi_musica[decada].append(tema)
except (ValueError, KeyError):
print("Hubo un error en el ingreso de datos. Intentá de nuevo")
except:
print("Ups! Algo ocurrió")
tema = input("Ingresá un nuevo tema (FIN para terminar): ")
mi_musica = {70: ["Stairway to heaven", "Bohemian Rhapsody"],
80: ["Dancing in the dark", "Welcome to the jungle", "Under pressure"],
2000:["Given up", "The pretender"]}
tema = input("Ingresá un nuevo tema (FIN para terminar): ")
while tema !="FIN":
try:
decada = int(input("ingresá a qué década pertenece: "))
mi_musica[decada].append(tema)
except (ValueError, KeyError):
print("Hubo un error en el ingreso de datos. Intentá de nuevo")
except:
print("Ups! Algo ocurrió")
tema = input("Ingresá un nuevo tema (FIN para terminar): ")
Ingresá un nuevo tema (FIN para terminar): Ascenso ingresá a qué década pertenece: veinte Hubo un error en el ingreso de datos. Intentá de nuevo Ingresá un nuevo tema (FIN para terminar): FIN
- ¿Cuándo se imprimiría el mensaje: "Ups! Algo ocurrió"?
Recordemos lo planteado la clase pasada: ¿qué debemos investigar para trabajar con excepciones?¶
- ¿Qué acción se toma después de levantada y manejada una excepción? ¿Se continúa con la ejecución de la unidad que lo provocó o se termina?
- ¿Cómo se alcanza una excepción?
- ¿Cómo especificar los manejadores de excepciones que se deben ejecutar cuando se alcanzan las mismas?
- ¿Qué sucede cuando no se encuentra un manejador para una excepción levantada?
- ¿El lenguaje tiene excepciones predefinidas?
- ¿Podemos levantar en forma explícita una excepción?
- ¿Podemos crear nuestras propias excepciones?
Ya respondimos algunas:¶
- ¿Qué acción se toma después de levantada y manejada una excepción? ¿Se continúa con la ejecución de la unidad que lo provocó o se termina?
- ¿Cómo se alcanza una excepción?
- ¿Cómo especificar los manejadores de excepciones que se deben ejecutar cuando se alcanzan las mismas?
- ¿Qué sucede cuando no se encuentra un manejador para una excepción levantada?
- ¿El lenguaje tiene excepciones predefinidas?
- ¿Podemos levantar en forma explícita una excepción?
- ¿Podemos crear nuestras propias excepciones?
Se puede agregar algo más...¶
La sentencia completa:
try:
sentencias
except excepcion1, excepcion2:
sentencias
except excepcion3 as variable:
sentencias
except:
sentencias
else:
sentencias
finally:
sentencias
Teníamos una tarea....¶
Veamos este ejemplo sencillo¶
In [8]:
Copied!
XY = 10
try:
print(XY)
except NameError:
print("Usaste una variable que no está definida")
else:
print("Este mensaje se imprime porque NO se levantó la excepción")
finally:
print("Este mensaje se imprime SIEMPRE")
XY = 10
try:
print(XY)
except NameError:
print("Usaste una variable que no está definida")
else:
print("Este mensaje se imprime porque NO se levantó la excepción")
finally:
print("Este mensaje se imprime SIEMPRE")
10 Este mensaje se imprime porque NO se levantó la excepción Este mensaje se imprime SIEMPRE
Entonces, ¿para qué usamos else y finally?¶
Repasemos todo con este otro ejemplo:¶
In [10]:
Copied!
dicci = {0:"Led Zeppelin", 2:"Deep Purple", 3:"Black Sabbath"}
y = 9
try:
print('Vamos a entrar a otro bloque TRY')
try:
for x in range(1,6):
print(dicci[z]) # OJO que estamos usando la variable z
except KeyError:
dicci[x] = 'Agregado'
y = y + 1
print(f"El valor de y es {y}")
except NameError:
print('OJO! Se está usando una variable que no existe')
print('Se sigue con las siguientes sentencias del programa')
dicci = {0:"Led Zeppelin", 2:"Deep Purple", 3:"Black Sabbath"}
y = 9
try:
print('Vamos a entrar a otro bloque TRY')
try:
for x in range(1,6):
print(dicci[z]) # OJO que estamos usando la variable z
except KeyError:
dicci[x] = 'Agregado'
y = y + 1
print(f"El valor de y es {y}")
except NameError:
print('OJO! Se está usando una variable que no existe')
print('Se sigue con las siguientes sentencias del programa')
Vamos a entrar a otro bloque TRY
--------------------------------------------------------------------------- NameError Traceback (most recent call last) Input In [10], in <cell line: 3>() 5 try: 6 for x in range(1,6): ----> 7 print(dicci[z]) # OJO que estamos usando la variable z 8 except KeyError: 9 dicci[x] = 'Agregado' NameError: name 'z' is not defined
- ¿Se ejecutaron las líneas 11 y 12?
El ejemplo demuestra que Python aplica el mecanismo de TERMINACIÓN.¶
Observemos el bloque finally en este otro ejemplo:¶
In [12]:
Copied!
dicci = {0:"Led Zeppelin", 2:"Deep Purple", 3:"Black Sabbath"}
y = 9
try:
print('Vamos a entrar a otro bloque TRY')
try:
for x in range(1,6):
print (dicci[z]) # OJO que estamos usando la variable z
except KeyError:
dicci[x] = 'Agregado'
finally:
y = y + 1
print(f"El valor de y es {y}")
print("Este texto no se imprime nunca!!!")
except NameError:
print('OJO! Se está usando una variable que no existe')
print('Se sigue con las siguientes sentencias del programa')
dicci = {0:"Led Zeppelin", 2:"Deep Purple", 3:"Black Sabbath"}
y = 9
try:
print('Vamos a entrar a otro bloque TRY')
try:
for x in range(1,6):
print (dicci[z]) # OJO que estamos usando la variable z
except KeyError:
dicci[x] = 'Agregado'
finally:
y = y + 1
print(f"El valor de y es {y}")
print("Este texto no se imprime nunca!!!")
except NameError:
print('OJO! Se está usando una variable que no existe')
print('Se sigue con las siguientes sentencias del programa')
Vamos a entrar a otro bloque TRY El valor de y es 10 OJO! Se está usando una variable que no existe Se sigue con las siguientes sentencias del programa
- ¿Se ejecutaron las líneas 11 y 12?
Y.. ¿qué sucede si no encuentra un manejador en esa primera búsqueda?¶
Observemos el siguiente ejemplo:¶
In [14]:
Copied!
def retornar_elemento(x):
dicci = {0:"Led Zeppelin", 2:"Deep Purple", 3:"Black Sabbath"}
try:
return dicci[x]
except NameError:
x = 0
print('Este código sirve para mostrar propagación dinámica.')
elem = int(input('Ingresá una clave para acceder al diccionario: (999 para finalizar) '))
while elem!=999:
try:
print (f"El valor del elemento: {elem} es {retornar_elemento(elem)}")
except KeyError:
print ('Ups! Entraste una clave inexistente. Probá de nuevo!')
elem = int(input('Ingresá clave para acceder al diccionario: (999 para finalizar) '))
def retornar_elemento(x):
dicci = {0:"Led Zeppelin", 2:"Deep Purple", 3:"Black Sabbath"}
try:
return dicci[x]
except NameError:
x = 0
print('Este código sirve para mostrar propagación dinámica.')
elem = int(input('Ingresá una clave para acceder al diccionario: (999 para finalizar) '))
while elem!=999:
try:
print (f"El valor del elemento: {elem} es {retornar_elemento(elem)}")
except KeyError:
print ('Ups! Entraste una clave inexistente. Probá de nuevo!')
elem = int(input('Ingresá clave para acceder al diccionario: (999 para finalizar) '))
Este código sirve para mostrar propagación dinámica. Ingresá una clave para acceder al diccionario: (999 para finalizar) assss
--------------------------------------------------------------------------- ValueError Traceback (most recent call last) Input In [14], in <cell line: 9>() 6 x = 0 8 print('Este código sirve para mostrar propagación dinámica.') ----> 9 elem = int(input('Ingresá una clave para acceder al diccionario: (999 para finalizar) ')) 10 while elem!=999: 11 try: ValueError: invalid literal for int() with base 10: 'assss'
- ¿Qué excepción se produce?¿Dónde se levanta? ¿Cuál es el bloque que termina?
- ¿Qué podemos decir sobre la forma de buscar el manejador de la excepción?
- Cuando no se encuentra un manejador para la excepción levantada, ¿dónde busca?
¿Qué sucedió?¶
- La excepción KeyError se levantó dentro de la función retornar_elemento.
- Busca estáticamene si el bloque está encerrado en otro bloque try except.
- Al no encontrar un manejador para esa excepción en la función ...
- Busca dinámicamente a quién llamó a la función.
- Si no encuentra un manejador... entonces termina el programa... con error.
¿Cómo es la forma de propagación que utiliza Python?¶
- Primero busca estáticamente.
- Si no se encuentra, busca dinámicamente a quién llamó a la función.
- Si no encuentra un manejador... entonces termina el programa ... con error..
Podemos levantar explícitamente excepciones¶
In [ ]:
Copied!
dicci = {0:"Led Zeppelin", 1:"Deep Purple", 4:"Black Sabbath"}
try:
print ('Entramos al bloque try')
for x in range(1,6):
if x == 2 or x == 3:
raise KeyError
else:
print (dicci[x])
print('Continuamos con el proceso..')
except KeyError:
dicci[x] = 'NUEVO'
dicci
dicci = {0:"Led Zeppelin", 1:"Deep Purple", 4:"Black Sabbath"}
try:
print ('Entramos al bloque try')
for x in range(1,6):
if x == 2 or x == 3:
raise KeyError
else:
print (dicci[x])
print('Continuamos con el proceso..')
except KeyError:
dicci[x] = 'NUEVO'
dicci
¿Por qué no continúa con la iteración e ingresa un elemento con clave 3?
También es posible:¶
In [15]:
Copied!
try:
print ('Entramos al bloque try')
for x in range(1,6):
if x == 2 or x == 3:
raise
else:
print (dicci[x])
print('Continuamos con el proceso..')
except KeyError:
print("Manejando KeyError")
try:
print ('Entramos al bloque try')
for x in range(1,6):
if x == 2 or x == 3:
raise
else:
print (dicci[x])
print('Continuamos con el proceso..')
except KeyError:
print("Manejando KeyError")
Entramos al bloque try Manejando KeyError
- ¿Qué excepción se levantó?
- raise: vuelve a lanzar la última excepción que estaba activa en el ámbito actual. Si no hay ninguna excepción activa en el alcance actual, se lanza una RuntimeError que indica que se trata de un error.
In [ ]:
Copied!
dicci = {0:"Led Zeppelin", 2:"Deep Purple", 3:"Black Sabbath"}
try:
print("Ingresamos al bloque try externo...")
try:
print ("Entramos al bloque try interno")
for x in range(1,6):
if x == 2 or x == 3:
raise KeyError
else:
print (dicci[x])
print("Continuamos con el proceso..")
except KeyError:
dicci[x] = 'NUEVO'
raise
except KeyError:
print("Vuelvo a manejar KeyError...")
except:
print("Esto es por cualquier otra...")
dicci
dicci = {0:"Led Zeppelin", 2:"Deep Purple", 3:"Black Sabbath"}
try:
print("Ingresamos al bloque try externo...")
try:
print ("Entramos al bloque try interno")
for x in range(1,6):
if x == 2 or x == 3:
raise KeyError
else:
print (dicci[x])
print("Continuamos con el proceso..")
except KeyError:
dicci[x] = 'NUEVO'
raise
except KeyError:
print("Vuelvo a manejar KeyError...")
except:
print("Esto es por cualquier otra...")
dicci
Algunas de las excepciones predefinidas (Built-in)¶
- ImportError: error con importación de módulos.
- ModuleNotFoundError: error por módulo no encontrado.
- IndexError: error por índice fuera de rango.
- KeyError: error por clave inexistente.
- NameError: error por nombre no encontrado.
- SyntaxError: error por problemas sintácticos
- ZeroDivisionError: error por división por cero.
- IOError: error en entrada salida.
¿Es posible acceder a la información de contexto de la excepción?¶
In [17]:
Copied!
dicci = {0:"Led Zeppelin", 2:"Deep Purple", 3:"Black Sabbath"}
try:
print ('Entramos al bloque try')
for x in range(1,6):
if x == 2 or x == 3:
raise KeyError
else:
print (dicci[x])
print('Continuamos con el proceso..')
except KeyError as exc:
dicci[x] = 'NUEVO'
datos_exc = exc
import sys
print(sys.exc_info())
print(datos_exc)
dicci = {0:"Led Zeppelin", 2:"Deep Purple", 3:"Black Sabbath"}
try:
print ('Entramos al bloque try')
for x in range(1,6):
if x == 2 or x == 3:
raise KeyError
else:
print (dicci[x])
print('Continuamos con el proceso..')
except KeyError as exc:
dicci[x] = 'NUEVO'
datos_exc = exc
import sys
print(sys.exc_info())
print(datos_exc)
Entramos al bloque try (<class 'KeyError'>, KeyError(1), <traceback object at 0x7f2a44348880>) 1
- sys.exc_info()
In [ ]:
Copied!
x = 10
y = 0
try:
z = x/y
except ZeroDivisionError as e:
z = e # representation: "<exceptions.ZeroDivisionError instance at 0x817426c>"
print(z) # output: "integer division or modulo by zero"
x = 10
y = 0
try:
z = x/y
except ZeroDivisionError as e:
z = e # representation: ""
print(z) # output: "integer division or modulo by zero"
En resumen:¶
try:
sentencias
except excepcion1, excepcion2:
sentencias
except excepcion3 as variable:
sentencias
except:
sentencias
else:
sentencias
finally:
sentencias
Desafío 2¶
- Dado el dataset con datos de video juegos del Apple store.
- Armar un menú con PySimpleGUi que permita:
- listar los juegos gratuitos disponibles en idioma español.
- los íconos (OPCIONAL en formato imagen, sino la url) de los 10 juegos con más calificaciones de usuarios (User Rating Count).
- Los que deseen, lo pueden subir a GitHub y compartir solución con @clauBanchoff
Incluir manejo de excepciones donde consideren adecuado.
También pueden descargar el archivo en: https://archivos.linti.unlp.edu.ar/index.php/s/D0YR0jqOx1GQtSD
Ayuda: para recuperar las imágenes de los íconos podemos usar el módulo requests
- Se instala con pip: pip install requests
- +Info
In [20]:
Copied!
# Ayuda para el punto 2
import requests
import os
juego = "pepe"
archivo = os.path.join(os.getcwd(), "archivos", juego)
icon_url = "https://cf.geekdo-images.com/original/img/lDN358RgcYvQfYYN6Oy2TXpifyM=/0x0/pic2437871.jpg"
icono = requests.get(icon_url)
# Ayuda para el punto 2
import requests
import os
juego = "pepe"
archivo = os.path.join(os.getcwd(), "archivos", juego)
icon_url = "https://cf.geekdo-images.com/original/img/lDN358RgcYvQfYYN6Oy2TXpifyM=/0x0/pic2437871.jpg"
icono = requests.get(icon_url)
In [21]:
Copied!
with open(f'{archivo}.jpg', 'wb') as f:
f.write(icono.content)
with open(f'{archivo}.jpg', 'wb') as f:
f.write(icono.content)