COMP 204 Exceptions Mathieu Blanchette based on material from Yue Li, Carlos Oliver Gonzalez and Christopher Cameron 1 / 31
Bugs: when things break I You will probably have noticed by now that things don’t always go as expected when you try to run your code. I We call this kind of occurrence a “bug”. I One of the first uses of the term was in 1946 when Grace Hopper’s software wasn’t working due to an actual moth being stuck in her computer. 1 1 Wikipedia 2 / 31
Types of bugs There are three major ways your code can go wrong. 1. Syntax errors 2. Exceptions (runtime) 3. Logical (semantic) errors 3 / 31
Syntax Errors: “Furiously sleep ideas green colorless.” 2 I When you get a syntax error it means you violated a writing rule and the interpreter doesn’t know how to run your code. I Your program will crash without running any other commands and produce the message SyntaxError with the o ff ending line and a ^ pointing to the part in the line with the error. I Game: spot the syntax errors! print("hello) 1 x = 0 2 while True 3 x = x + 1 4 mylist = ["bob" 2, False] 5 if x < 1: 6 print("x less than 1") 7 2 Noam Chomsky (1955) 4 / 31
Exceptions: “Colorless green ideas sleep furiously” 3 I If you follow all the syntax rules, the interpreter will try to execute your code. I However, the interpreter may encounter into code it is unable to execute, so it raises an Exception I The program has to deal with this Exception if it is not handled, execution aborts. I Note: unlike with syntax errors, all the instructions before the interpreter reaches an exception do execute. I Here is a list of all the built-in exceptions and some info on them. 3 Noam Chomsky (1955) 5 / 31
Exceptions: ZeroDivisionError I There are many types of exceptions, and eventually you will also be able to define your own exceptions. I I’ll show you some examples of common Exceptions. I ZeroDivisionError x = 6 1 y = x / (x - 6) #syntax is OK, executing fails 2 3 File "test.py", line 2, in <module> 4 y = x / (x - 6) 5 ZeroDivisionError: integer division or modulo by 6 zero , → 6 / 31
Exceptions: NameError I Raised when the interpreter cannot find a name-binding you are requesting. I Usually happens when you forget to bind a name, or you are trying to access a name outside your namespace. def foo(): 1 x = "hello" 2 foo() 3 print(x) 4 Traceback (most recent call last): 5 File "exceptions.py", line 4, in <module> 6 print(x) 7 NameError: name 'x' is not defined 8 7 / 31
Exceptions: IndexError I Raised when the interpreter tries to access a list index that does not exist mylist = ["bob", "alice", "nick"] 1 print(mylist[len(mylist)]) 2 3 Traceback (most recent call last): 4 File "exceptions.py", line 2, in <module> 5 print(mylist[len(mylist)]) 6 IndexError: list index out of range 7 8 / 31
Exceptions: TypeError I Raised when the interpreter tries to do an operation on a non-compatible type. >>> mylist = ["bob", "alice", "nick"] 1 >>> mylist + "mary" 2 3 Traceback (most recent call last): 4 File "<stdin>", line 1, in <module> 5 TypeError: can only concatenate list (not "int") to 6 list , → 7 # this is okay 8 >>> mylist * 2 9 ["bob", "alice", "nick", "bob", "alice", "nick"] 10 9 / 31
Traceback What happens when an Exception is raised? The program’s normal control flow is altered. I The execution of the block of code stops I Python looks for code to handle the Exception (try/except block; see later) I If it doesn’t find that code, it stops the program and produces a traceback message that tells you where the error was raised, which function it sits in, what code called that function, etc. I See example on next slide... 10 / 31
Traceback I When an exception is raised, you get a traceback message which tells you where the error was raised. def foo(): 1 return 5 / 0 2 def fee(): 3 return foo() 4 fee() 5 6 Traceback (most recent call last): 7 File "exception.py", line 5, in <module> 8 fee() 9 File "exception.py", line 4, in fee 10 return foo() 11 File "exception.py", line 2, in foo 12 return 5 / 0 13 ZeroDivisionError: division by zero 14 11 / 31
Traceback (exceptions can be caused by user input) 1 def BMI( weight , h e i g h t ) : p r i n t ( ”Computing BMI” ) 2 bmi = weight / ( h e i g h t h e i g h t ) 3 ∗ p r i n t ( ”Done computing BMI” ) 4 r e t u r n bmi 5 6 7 def get BMI from user ( ) : w = i n t ( i n p u t ( ” Please e n t e r weight ” ) ) 8 h = i n t ( i n p u t ( ” Please e n t e r h e i g h t ” ) ) 9 bmi = BMI(w, h ) 10 r e t u r n bmi 11 12 13 myBMI = get BMI from user ( ) 14 # Output : 15 # Please e n t e r weight 4 16 # Please e n t e r h e i g h t 0 17 # Computing BMI 18 # Traceback ( most r e c e n t c a l l l a s t ) : 19 # F i l e ” excTraceBack . py ” , l i n e 13 , i n < module > 20 # myBMI = get BMI from user ( ) 21 # F i l e ” excTraceBack . py ” , l i n e 10 , i n < module > 22 # bmi = BMI(w, h ) 23 # F i l e ” excTraceBack . py ” , l i n e 3 , i n < module > 24 # r e t u r n weight / ( h e i g h t h e i g h t ) ∗ 25 # b u i l t i n s . Z e r o D i v i s i o n E r r o r : d i v i s i o n by zero 12 / 31
When Exceptions is not handled I If a function generates an Exception but does not handle it, the Exception is send back to the calling block. I If the calling block does not handle the exception, the Exception is sent back to its calling block... etc. I If no-one handles the Exception, the program terminates and reports the Exception. function function call call bmi = weight/(height*height) BMI(w,h) get_BMI_from_user() ZeroDivisionError exception ZeroDivisionError exception 13 / 31
Handling Exceptions: try and except A program can provide code to handle an Exception, so that it doesn’t crash when one happens. I To be able to handle an exception generated by a piece of code, that code needs to be within a try block. I If the code inside the try block raises an exception, its execution stops and the interpreter looks for code to handle the Exception. I Code for handling Exception is in the except block. try: 1 # do something that may cause an Exception 2 # some more code 3 except <SomeExceptionType>: 4 # do something to handle the Exception 5 # rest of code 6 If L2 raises an Exception of type SomExceptionType, we jump to L4, without executing L3 If L2 doesn’t cause an exception, L3 is executed, and L4 and 5 are not executed. 14 / 31 In both cases, the program continues executing with L6.
1 def BMI( weight , h e i g h t ) : p r i n t ( ”Computing BMI” ) 2 t r y : 3 bmi = weight / ( h e i g h t h e i g h t ) 4 ∗ p r i n t ( ”Done computing BMI” ) 5 except Z e r o D i v i s i o n E r r o r : 6 p r i n t ( ” There was a d i v i s i o n by zero ” ) 7 bmi = − 1 # a s p e c i a l code to i n d i c a t e an e r r o r 8 r e t u r n bmi 9 10 11 def get BMI from user ( ) : t r y : 12 w = i n t ( i n p u t ( ” Please e n t e r weight ” ) ) 13 h = i n t ( i n p u t ( ” Please e n t e r h e i g h t ” ) ) 14 except : 15 p r i n t ( ” i n v a l i d i n p u t s ” ) 16 r e t u r n 0 17 bmi = BMI(w, h ) 18 p r i n t ( ”Thank you ! ” ) 19 r e t u r n bmi 20 21 22 myBMI = get BMI from user ( ) 23 24 # Output : 25 # Please e n t e r weight 4 26 # Please e n t e r h e i g h t 0 27 # Computing BMI 28 # There was a d i v i s i o n by zero 15 / 31 # Thank you !
Where do exceptions come from? We raise them I Exceptions come from raise statements. I Syntax: raise [exception object] I You can choose to raise any exception object. Obviously a descriptive exception is preferred. I You can even define your own exceptions (out of scope). def my_divide(a, b): 1 if b == 0: 2 raise ZeroDivisionError 3 else: 4 return a / b 5 def my_divide(a, b): 6 if b == 0: 7 raise TypeError # we can raise any exception 8 we want , → else: 9 return a / b 10 16 / 31
We can raise an informative exception 1 # This BMI f u n c t i o n r a i s e s a ValueError Exception 2 # i f the weight or h e i g h t are < = 0 3 def BMI( weight , h e i g h t ) : i f weight < =0 or h e i g h t < = 0 : 4 r a i s e ValueError ( ”BMI handles only p o s i t i v e v a l u e s ” ) 5 p r i n t ( ”Computing BMI” ) 6 r e t u r n weight / ( h e i g h t h e i g h t ) 7 ∗ 8 9 def get BMI from user ( ) : w = i n t ( i n p u t ( ” Please e n t e r weight ” ) ) 10 h = i n t ( i n p u t ( ” Please e n t e r h e i g h t ” ) ) 11 bmi = BMI(w, h ) 12 p r i n t ( ”Thank you ! ” ) 13 r e t u r n bmi 14 15 16 myBMI = get BMI from user ( ) 17 18 # Traceback ( most r e c e n t c a l l l a s t ) : 19 # F i l e ” excTraceBack . py ” , l i n e 16 , i n < module > 20 # myFunction ( ) 21 # F i l e ” excTraceBack . py ” , l i n e 12 , i n < module > 22 # r = r a t i o (5 ,0) 23 # F i l e ” excTraceBack . py ” , l i n e 5 , i n < module > 24 # r a i s e ValueError (”BMI handles only p o s i t i v e v a l u e s ”) 25 # b u i l t i n s . ValueError : BMI handles only p o s i t i v e v a l u e s 17 / 31
Recommend
More recommend