Exceptions
Consider the following simple program… We have to travel 100 miles Ask the user for a speed to enter (in mph) Tell them the time, in hours, it will take to arrive denom = int(input("Enter a speed in mph: ")) print(100/denom , “ hours to travel 100 miles.”)
Consider the following simple program… We have to travel 100 miles Ask the user for a speed to enter (in mph) Tell them the time, in hours, it will take to arrive denom = int(input("Enter a speed in mph: ")) print(100/denom , “ hours to travel 100 miles.”) This will crash if input is zero, though! ZeroDivisionError: division by zero
Error When Python crashes, it always gives an error: IndexError Accessing an index out of bounds in a list KeyError Acessing a dictionary key that doesn’t exist TypeError Performing an illegal interaction between types (“2” + 2) NameError Referencing a variable that hasn’t been created yet ValueError Function takes in a value it can’t use: int(“cat”), for example Typically, an error will crash the program…unless you catch it!
Preventing the error denom = 0 while denom <= 0: denom = int(input("Enter a speed in mph: ")) if (denom <= 0): print("Error: speed must be greater than zero! Try Again!") print(100/denom, " hours to travel 100 miles.") This won’t crash!
But what if we can’t prompt the user? Imagine you are writing the back end of a system You are implementing the backend in Python, but you don’t have access to the front end You can’t prompt the user You are writing a function that takes in two numbers: distance – the distance to be traveled in MPH speed – the speed to travel in MPH At this point, having a ZeroDivisionError is the correct action if the speed is zero Whoever is calling your function needs to call it correctly Not your job to change the input!
Why raise errors? "a common mistake that people make when trying to design something completely foolproof is to underestimate the ingenuity of complete fools“ – Douglas Adams, Mostly Harmless If you are writing a function, you can’t change how people call the function But you can force the person using your function to use it correctly Raising and error informs a user they are using the function wrong Avoids “easy to miss” garbage -in garbage-out
Example The below is fine: def travel_time(distance, speed): return distance / speed travel_time(5, 0) # throws a zero division error The end user shouldn’t be calling your function like this. Are there any other ways the function travel_time shouldn’t be called?
Travel_time errors What if the type is off? travel_time("sheep", [2, 3, 5]) This looks absurd, but this compiles and runs (albeit crashing due to a type error) What if distance or velocity is negative? This wouldn’t make sense, so can we prevent it? As the function is written, it would return output, but is that output useful?
Raising Errors You can raise errors! def travel_time(distance, speed): if (distance < 0): raise ValueError("travel_time distance cannot be negative") if (speed < 0): raise ValueError("travel_time speed cannot be negative") return distance / speed travel_time(-5, 10) This is called “defensive programming” Making sure your code can’t be called in an incorrect way
What to do with Error If you call a function or perform an operation that could result in an error, you can try to “catch” the error You can “catch” the error in order to handle it Format: try: code that could throw an error except <KindOfError>: handling the exception
Example What if when you get user input, the user enters invalid input? distance = 0; while distance == 0: try: distance = float(input("Enter a distance to travel in miles:")) except ValueError: print("You didn't enter a number. Please try again!") Now, instead of crashing, we can catch the error, and just make the user try again!
Error Tracing examples https://storage.googleapis.com/cs1111/examples/exception/exce ption-tracing1.py There are actually 12, just change the last part of the url to: exception-tracing[x].py Where x is a number 1-12
Recommend
More recommend