In [1]:
print(Q)
In [2]:
1 + 'abc'
In [3]:
2 / 0
In [4]:
L = [1, 2, 3]
L[1000]
Pero Python es tan lindo que nos da un montón de información sobre dónde está el error.
In [5]:
try:
print("this gets executed first")
except:
print("this gets executed only if there is an error")
El segundo bloque de código no se ejecuta porque el primero no reportó ningún error. Pongamos un problema, entonces!
In [7]:
try:
print("let's try something:")
x = 1 / 0 # ZeroDivisionError
except:
print("something bad happened!")
Cuando algo pasa en el bloque try
(una division por cero, en este caso), el error fue "caught" (atrapado) y el bloque except
se ejecuta.
Una de las cosas para lo que se usa esto es para chequear "user input" o "file input", que son temas de la próxima clase. Pero nos podemos imaginar una función que sea más amistosa, y nos permita dividir por cero. Por ejemplo:
In [8]:
def safe_divide(a, b):
try:
return a / b
except:
return 1E100
In [9]:
safe_divide(1, 2)
Out[9]:
In [10]:
safe_divide(2, 0)
Out[10]:
Pero qué pasa si la excepción es de otra clase?
In [12]:
safe_divide (1, '2') # esto no es división por cero XD
Out[12]:
la división por un string "raises" (levanta?) una excepción llamada TypeError
, pero nuestro código asume que cualquier cosa es un ZeroDivisionError
, lo cual es erróneo. A veces es mejor "agarrar" (catch) las excepciones explicitamente.
In [13]:
def safe_divide(a, b):
try:
return a / b
except ZeroDivisionError:
return 1E100
In [14]:
safe_divide(1, 0)
Out[14]:
In [15]:
safe_divide(1, '2')
Ahora podemos entonces agarrar los errores específicos de "división por cero", y dejar pasar los otros normalmente.
In [16]:
raise RuntimeError("my error message")
For example, take our fibonacci function:
In [17]:
def fibonacci(N):
L = []
a, b = 0, 1
while len(L) < N:
a, b = b, a + b
L.append(a)
return L
Pero N
puede ser negativo! Errores que se originan en valores pasados por argumentos, se llaman ValueErrors
.
In [18]:
def fibonacci(N):
if N < 0:
raise ValueError("N must be non-negative")
L = []
a, b = 0, 1
while len(L) < N:
a, b = b, a + b
L.append(a)
return L
In [19]:
fibonacci(10)
Out[19]:
In [20]:
fibonacci(-10)
Ahora el usuario sabe que el "input" es inválido. Y hasta podemos usar un try...except
In [21]:
N = -10
try:
print("trying this...")
print(fibonacci(N))
except ValueError:
print("Bad value: need to do something else")
Hay veces que podemos ser más expresivos todavía en el manejo de flujo.
In [22]:
try:
print("try something here")
except:
print("this happens only if it fails")
else:
print("this happens only if it succeeds")
finally:
print("this happens no matter what")
finally
es como un estadio de limpieza del código (cerrar archivos, volver variables a 0, meh...)