6.0 - Exceptions in Python
6.0 - Exceptions in Python
• # Possible output:
• # Please enter an even number: 2
• # The number entered is valid, thank you!
Raising an Exception
• You can also raise a specific error if needed:
• user_input = int(input("Please enter an even number:
"))
• if (user_input % 2) == 0:
• print("The number entered is valid, thank you!")
• else:
• raise ValueError("Invalid input!")
• # Possible output:
• # Please enter an even number: 5
• # ValueError: Invalid input!
Types of Exceptions
1. TypeError: Raised when an operation or function is applied to
an object of inappropriate type. Example is trying to add a string
and an integer.
x = "5"
y = 10
z = x + y
2. ValueError: Raised when a function or operation receives an
argument that has the correct type but improper value is passed
to a method or function.
Types of Exceptions
3. NameError: Raised when a variable or name is not defined in
the current scope. For example is trying to use a variable that
has not been defined.
x = y + 5 # Raises a NameError: name 'y' is not defined
4. IndexError: Raised when you try to access an index that is out
of range for a sequence. For example is trying to access an index
that does not exist in a list.
my_list = [1, 2, 3]
x = my_list[5] # Raises an IndexError: list index out of range
Types of Exceptions
5. KeyError: Raised when you try to access a key that does not exist in a dictionary. For
example is trying to access a key that does not exist in a dictionary
my_dict = {"a": 1, "b": 2}
x = my_dict["c"] # Raises a KeyError: ‘c’
6. Attribute Error: This can happen when you try to access an attribute that doesn't exist, or
when you try to call a method that isn't defined for that object. For example:
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
person1 = Person("Alice", 25)
print(person1.address) # Raises an AttributeError: 'Person'
object has no attribute 'address'
Effects of an Exception
• When raising an exception, it appears to stop the program
execution immediately.
• Any lines that were supposed to run after the exception is
raised are not executed.
• This can be prevented, but if it is not, the program will exit with
an error message.
• An example of this can be seen in the next slide.
Effects of an Exception
• Here is a program where we raise an exception ourselves:
• def broken_function():
• print("Hello, I would like a burger.")
• raise Exception("Sorry, we don't have any burgers.")
• print("I would also like large fries.")
• print("And a diet coke please.")
• try:
• broken_function()
• except:
• print("Whoops! Turns out we have burgers after all!")
• print("Sorry, but could you repeat your order?")
Handling Exceptions
• Looking at the previous code, there are some important things
to take note for catching the exception.
• The “try… execpt” clause allows us to stop an exception from
crashing the program.
• This allows the program to continue running, but it causes the
rest of the code in the “broken_function()” to not execute.
• The code within the “except” block will be executed instead
along with any code after the “try… except” block.
Handling Exceptions
• The issue with simply using “except” is that it will catch any
type of exception.
• We might want to catch specific exceptions instead:
• while True:
• user_input = input("Please enter a number: ")
• try:
• int_test = int(user_input)
• break
• except ValueError:
• print("You did not enter a number!")
Handling Exceptions
• We can also catch multiple exceptions if we are expecting
different types of errors.
• This allows us to have different error messages depending on
the arguments or the code placed in the “try” block.
• To stack multiple exceptions, we simply repeat the “except”
keyword with a different error type.
• An example of this is shown in the next slide.
Handling Exceptions
• We can catch multiple exceptions in Python:
• while True:
• user_input = input("Please enter a number between 0 and 10:
")
• try:
• int_test = int(user_input)
• if (int_test < 0) or (int_test > 10):
• raise Exception("You entered a number that isn't 0
to 10!")
• break
• except ValueError:
• print("You did not enter a number!")
• except Exception:
• print("Do not enter a number lower than 0 or greater
than 10!")
Handling Exceptions
• We can set multiple exceptions and call them if they occur in the
code as seen in the example.
• Something to keep in mind is that when stacking exceptions,
only the first matching clause will be run.
• This is the case even if the code raises multiple exceptions.
Handling Exceptions
• You can also “capture” the contents of an exception.
• This allows us to place the contents of the exception into a
variable.
• This will allow us to print the error which caused the exception
to be raised.
• The syntax for this is as follows:
• try:
• raise ValueError("This is an argument")
• except ValueError as e:
• print("The exception arguments were:", e)
Handling Exceptions
• We can use the value of the exceptions as part of our error messages:
• while True:
• user_input = input("Please enter an even number: ")
• try:
• int_test = int(user_input)
• if (int_test % 2) == 0:
• print("The number entered is an even number, thank you!")
• else:
• raise ValueError(int_test)
• break
• except ValueError as e:
• print("You entered:'", e, "' which is not an even number!")
ELSE Block
• In Python, a “try… except” clause can make use of the “else”
keyword, like “if” blocks or “while” blocks.
• Code in an “else” block will only be run if no exceptions were raised
by the code in the “try” block.
• The syntax of the “else” block is as follows:
• try:
• code blocks here...
• except:
• code that will run when an exception is called...
• else:
• code that will run if no exceptions are thrown...
ELSE Block
• We can see how the “else” keyword is used in this example:
• while True:
• user_input = input("Please enter a number: ")
• try:
• int_test = int(user_input)
• except ValueError:
• print("You did not enter a number!")
• else:
• print("You did not enter any incorrect inputs! Nice job!")
• break
ELSE Block
• The last section of code, will only execute if no exceptions are
thrown by the “try” block.
• Additionally, one characteristic of the “else” block is that you
can also throw exceptions from this block.
• What makes it different is that exceptions will not be caught if
they are placed in this block.
• This means that if you raise an exception in the “else” block, it
will cause your program to crash and give an error.
FINALLY Block
• Another keyword that you can use with the “try… except” clause is
the “finally” keyword.
• The code in a “finally” block will be executed regardless of whether
any exceptions were raised in the “try” block.
• The syntax of the “finally” block is as follows:
• try:
• code blocks here...
• except:
• code that will run when an exception is called...
• finally:
• code that will run whether or not exceptions are
thrown...
FINALLY Block
• An example of this keyword in use is seen below:
• while True:
• user_input = input("Please enter a number: ")
• try:
• int_test = int(user_input)
• break
• finally:
• print("Thank you for your input!")
FINALLY Block
• Take note that the code in the “finally” block will always
execute even when an exception is called.
• This means that if exceptions are called, the code in the “finally”
block will be executed multiple times.
• Like the “else” block, you can also throw exceptions from the
“finally” block.
• This means that if you raise an exception in the “finally” block,
it will also cause your program to crash and give an error.
FINALLY Block
• Take note that when combining both the “else” keyword and
“finally” keyword, they are arranged in this order:
• try:
• code blocks here...
• except:
• code that will run when an exception is called...
• else:
• code that will run if no exceptions are thrown...
• finally:
• code that will run whether or not exceptions are
thrown...
Activity
• Create a python program that asks for the birth year of the user and
outputs the current age. Use the skeleton below to create a common
sense program.
• try:
• code blocks here...
• except:
• code that will run when an exception is called...
• else:
• code that will run if no exceptions are thrown...
• finally:
• code that will run whether or not exceptions are
thrown...
Hierarchy of Exceptions
• Exception handling occurs based on an exception hierarchy,
determined by the inheritance structure of the exception classes.
• Most exception types are subclasses of the “Exception” class.
• This means that when we try to catch an “Exception” error, we
are catching all the possible errors underneath it.
• There are exceptions to this, such as the “SystemExit” class and
the “KeyboardInterrupt” class.
• These two, along with the “Exception” class, are subclasses of
the “BaseException” class.
Hierarchy of Exceptions
• What this means in practice is that if we raise an exception for
an error class, we will also catch errors in the sub classes.
• An example of this is the “ArithmeticError” class, show below.
• ArithmeticError
• FloatingPointError
• OverflowError
• ZeroDivisionError
• The “ArithmeticError” class has three subclasses, which we can
catch if we call the “ArithmeticError” class instead.
Hierarchy of Exceptions
• An example of this concept in practice is seen below:
• user_input = int(input("Please enter an number that is not
zero: "))
• try:
• output = 10 / user_input
• print("Your number divided by 10 is equal to", output)
• except ArithmeticError as e:
• print("An error occured:", e)
• The code will give a “divide by zero” error if we enter “0”.
Defining New Exceptions
• We might want to create custom exceptions, if we find the
current list of built-in exceptions insufficient.
• We define an exception in a similar way to defining a class.
• The name of the class will be the exception name, and we can
also provide additional arguments in the initializer as needed.
• We then have the class inherit the “Exception” class.
• This will turn it into an error class that can be raised and caught
by a “try… catch” clause.
Defining New Exceptions
• An example new exception is shown below:
• class InvalidWithrdawal(Exception):
• pass
• def over_balance(self):
• excess_balance = self.amount - self.balance
• return excess_balance
• def over_balance(self):
• excess_balance = self.amount - self.balance
• return excess_balance
• try:
• raise InvalidWithdrawl(25, 50)
• except InvalidWithdrawl as e:
• print("I'm sorry, but your withdrawal is "
• "more than your balance by "
• "${}".format(e.over_balance()))