Lecture 20
Exceptions
Exceptions
Why?
Exceptions
Raising Exceptions
Raise Statements
Exceptions are raised with a raise statement
<expression> must evaluate to a subclass of BaseException or an instance of one.
Exceptions are constructed like any other object. E.g., TypeError('Bad argument!')
Raise Statements
Exceptions are raised with a raise statement
<expressions> must evaluate to a subclass of BaseException or an instance of one
Exceptions are constructed like any other object. E.g., TypeError('Bad argument!')
Raise Statements
Exceptions are raised with a raise statement
<expressions> must evaluate to a subclass of BaseException or an instance of one
Exceptions are constructed like any other object. E.g., TypeError('Bad argument!')
Demo
Problem
Problem
Write a function that takes a list of numbers representing ages. They should be over 21, and the list of names, then prints the invitations.
def invites(names, ages):
for i in range(len(ages)):
if (ages[i] < 21):
raise ValueError("Too young to come")
else:
print("{} is above 21. {}, you are invited.".format(ages[i], names[i]))
invites(["Tom", "Mary", "Rosa"], [23, 44, 87])
Problem
def invites(names, ages):
for i in range(len(ages)):
if (ages[i] < 21):
raise ValueError("Too young to come")
else:
print("{} is above 21. {}, you are invited.".format(ages[i], names[i]))
invites(["Tom", "Mary", "Rosa"], [23, 44, 87])
23 is above 21. Tom, you are invited.
44 is above 21. Mary, you are invited.
87 is above 21. Rosa, you are invited.
Problem
def invites(names, ages):
for i in range(len(ages)):
if (ages[i] < 21):
raise ValueError("Too young to come")
else:
print("{} is above 21. {}, you are invited.".format(ages[i], names[i]))
invites(["Tom", "Mary", "Rosa"], [13, 44, 87])
Traceback (most recent call last):
File "/Users/marinalanglois/Desktop/tt.py", line 9, in <module>
invites(["Tom", "Mary", "Rosa"], [13, 44, 87])
File "/Users/marinalanglois/Desktop/tt.py", line 4, in invites
raise ValueError("Too young to come")
ValueError: Too young to come
Try Statements
Try statements
Try statements handle exceptions
Handling Exceptions
Exception handling can prevent a program from terminating
Handling Exceptions
Exception handling can prevent a program from terminating
Handling Exceptions
Exception handling can prevent a program from terminating
Handling Exceptions
Exception handling can prevent a program from terminating
Handling Exceptions
Exception handling can prevent a program from terminating
Try statements
Try statements handle exceptions
Execution rule:
Handling Exceptions
Exception handling can prevent a program from terminating
Multiple try statements: Control jumps to the except suite of the most recent try statement that handles that type of exception
WWPD? Demo
WWPD?
A: ZeroDivisionError: division by zero
B: Never printed if x is 0
C: 'division by zero' # str(e)
D: Something else
WWPD?
A: ZeroDivisionError: division by zero
B: Never printed if x is 0
C: 'division by zero' # str(e)
D: Hello!
E: Something else
WWPD?
A: NameError
B: ZeroDivisionError: division by zero
C: Something else, your questions are tricky
Multiple Excepts
try:
You do your operations here;
......................
except ExceptionI:
If there is ExceptionI, then execute this block.
except ExceptionII:
If there is ExceptionII, then execute this block.
......................
else:
If there is no exception then execute this block.
try-except-else
try:
fh = open("testfile", "w")
fh.write("Writing something to the file")
except IOError:
print "Error: file does not exist"
else:
print("Success!")
fh.close()
What is the output?
def handling_invites(names, ages): # does not crash
try:
invites(names, ages)
except ValueError as e:
print(e)
handling_invites(["Tom", "Mary", "Rosa"], [13, 44, 87])
def invites(names, ages):
for i in range(len(ages)):
if (ages[i] < 21):
raise ValueError("Too young to come")
else:
print("{} is above 21. {}, you are invited.".format(ages[i], names[i]))
What is the output?
def handling_invites(names, ages): # does not crash
try:
invites(names, ages)
except ValueError as e:
print(e)
handling_invites(["Tom", "Mary", "Rosa"], [13, 44, 87])
Too young to come
def invites(names, ages):
for i in range(len(ages)):
if (ages[i] < 21):
raise ValueError("Too young to come")
else:
print("{} is above 21. {}, you are invited.".format(ages[i], names[i]))
Output?
def even_better(names, ages):
for i in range(len(ages)):
try:
if (ages[i] < 21):
raise ValueError("Too young to come")
else:
print("{} is above 21. {}, you are invited.".format(ages[i], names[i]))
except ValueError as e:
print("Sorry {}, you are too young".format(names[i]))
even_better(["Tom", "Mary", "Rosa"], [13, 44, 87])
def invites(names, ages):
for i in range(len(ages)):
if (ages[i] < 21):
raise ValueError("Too young to come")
else:
print("{} is above 21. {}, you are invited.".format(ages[i], names[i]))
Output?
def even_better(names, ages):
for i in range(len(ages)):
try:
if (ages[i] < 21):
raise ValueError("Too young to come")
else:
print("{} is above 21. {}, you are invited.".format(ages[i], names[i]))
except ValueError as e:
print("Sorry {}, you are too young".format(names[i]))
>>> even_better(["Tom", "Mary", "Rosa"], [13, 44, 87])
Sorry Tom, you are too young
44 is above 21. Mary, you are invited.
87 is above 21. Rosa, you are invited.
def invites(names, ages):
for i in range(len(ages)):
if (ages[i] < 21):
raise ValueError("Too young to come")
else:
print("{} is above 21. {}, you are invited.".format(ages[i], names[i]))
Split the work
def invites(name, age): # you wrote this function
if (age < 21):
raise ValueError("Too young to come")
else:
print("{} is above 21. {}, you are invited.".format(age, name))
def even_better(names, ages): # I use your function
for i in range(len(ages)):
try:
invites(names[i], ages[i])
except ValueError as e:
print("Sorry {}, you are too young".format(names[i]))
even_better(["Tom", "Mary", "Rosa"], [13, 44, 87])
More examples
>>> x = 17 + “Marina”
More
>>> x = 17 + “Marina”
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for +: 'int' and 'str'
Do not do it, although Python allows you to
try:
x = 17 + "Marina"
except:
print("Oouch")
Oouch
Pass: ignore and move on
try:
x = 17 + "Marina"
except:
pass
(cont.code from here)
Nothing will happen and the code resumes its execution from (cont. from here)
Pass: ignore and move on
try:
x = 17 + "Marina"
except:
pass
Nothing will happen
Can be used with for/while loops as well
Difference between pass and continue
Pass is just a placeholder. When you use the 'pass' statement, nothing occurs, but it stops errors when you can't have an empty code.
What do you think will happen?
try:
a = 1/0
except NameError as e:
print("printed error")
A: printed error
B: infinity
C: ZeroDivisionError: division by zero
D: ZeroDivisionError: division by zero AND printed error
E: Something else
Difference between assert and exception
https://stackoverflow.com/questions/40182944/difference-between-raise-try-and-assert
Quick recap about exceptions
>>> try:
... {}["name"]
... except KeyError as e:
... print("bad key!")
Quick recap about exceptions
>>> try:
... {}["name"]
... except KeyError as e:
... print("bad key!")
bad key!
Quick recap about exceptions
try:
{}["name"]
except KeyError as e:
print("bad key!")
lst = [3, 4, 5]
lst.append(6)
print(lst)
bad key!
[3, 4, 5, 6]
Quick recap: your code can raise exceptions too
def sum_them(dict1, dict2):
# same keys, at least one even key
# add values for only even keys
"""
>>> dict1 = {1:1, 2:2}
>>> dict2 = {1:-1, 2: -2}
>>> sum_them(dict1, dict2)
{2:0}
"""
output = {}
for key in dict1:
if key%2==0:
output[key] = dict1[key] + dict2[key]
return output
Quick recap: your code can raise exceptions too
def sum_them(dict1, dict2):
# same keys, at least one even key
# add values for only even keys
output = {}
for key in dict1:
if key%2==0:
output[key] = dict1[key] + dict2[key]
if len(output)==0:
raise KeyError("Must be at least one even key")
return output
Another function can handle it
def sum_them(dict1, dict2):
output = {}
for key in dict1:
if key%2==0:
output[key] = dict1[key] + dict2[key]
if len(output)==0:
raise KeyError("Must be at least one even key")
return output
def many_sums_v1(*args):
lst = []
first_list = args[0::2]
second_list = args[1::2]
combined=list(zip(first_list, second_list))
try:
for item in combined:
lst.append(sum_them(*item))
except KeyError:
lst.append({0:0})
return lst