Lab 08 - Exceptions
Due by 11:59pm on 2023-07-13.
Starter Files
Download lab08.zip. Inside the archive, you will find starter files for the questions in this lab.
Topics
In this lab we'll discussing exceptions and try-catch blocks.
Required Questions
Q1: In Range and an Occasional Error
Write a function in_range that checks if input is within the range of 1-100 and returns False if not.
def in_range(input):
"""Write a function that checks to see if input is
within the range of 1-100 and have it return False if not
>>> in_range(9)
True
>>> in_range(-4)
False
"""
"*** YOUR CODE HERE ***"
Next, write code in the main function that generates 1000 random numbers between 1 and 101 (to simulate an infrequent error) and calls the in_range function to validate the number generated. It should print out a message if the number is bad.
Intro to Exceptions
When we're writing code, our programs might run into different types of errors. A function might receive a string when it was only designed to accept integers. A connection across a network may be lost or some file is not available.
We handle these errors with exceptions. We use these to interrupt the program, signal some sort of error, and then return to running the program. An excepetion can be handled with a try statement. A try statement has two parts; the try block and the except block.
try:
<try suite>
except <exception class> as <name>:
<except suite>
For example, lets say we had a simple division function.
def div(numerator, denominator):
return numerator / denominator
If div was passed 0 as denominator, then the code would error out. To handle this we might use try.
def div(numerator, denominator):
try:
return numerator / denominator
except ZeroDivisionError as e:
print(f'Invalid denominator: {denominator}. Error: {type(e)}')
return 0
In addition to errors caused by bad code, we can purposely create exceptions using the key word raise. We call this raising an excpetion. When an exception is raised, it interrupts the normal flow of the program and if there is a try/catch block, it transfers control to handle the exception.
Python has a wide range of built-in exception types that represent different categories of errors, such as ValueError, TypeError, ZeroDivisionError, IndexError, etc. You can also define custom exception classes by inheriting from the base Exception class or its subclasses.
class CustomException(Exception):
pass
def div(numerator, denominator):
if denominator == 0:
raise CustomException("Cannot divide by zero!")
result = numerator / denominator
return result
try:
result = divide_numbers(10, 0)
print(result)
except CustomException as e:
print(f"An error occurred: {type(e)}")
Q2: Do it again. Except better.
Redo the first step but throwing an exception using a try/catch block.
def in_range2(input):
'''Write a function that throws an exception if input is not between 1
and 100. It should return None otherwise'''
Note: Make sure you raise an exception in one function and use a try/catch in the other.
Q3: In Bounds
In your Grid.py from lab07, add an in_bounds() method that takes x and y coordinates and returns True if the (x, y) postion is in bounds of the grid (i.e. x < image.width and y < image.height). It should return False otherwise.
def in_bounds(self, x, y):
Then add exception throwing to the get and set methods to prevent them for acessing parts of the grid that are out of bounds. They should call in_bounds() and raise an IndexError exception if the coordinates are out of bounds.
Submit
If you are not in lab today, submit your lab08.py file along with your Grid.py file to Gradescope to receive credit.
Submissions will be in Canvas.
Otherwise, thanks for coming to lab! You don't have to submit anything.