Python Python Basics All Together Now Handle Exceptions

Raising Exceptions

Under what circumstances do we raise an exception?

1 Answer

Eric McKibbin
MOD
Eric McKibbin
Treehouse Moderator 11,177 Points

This is a great question, and I look forward to reading answers from more experienced programmers!

While it's got no answers though, I'll put down my thoughts.

There's a few components to this. try, except, and raise.

try/except can be reasonably straightforward in a lot of circumstances, we're using a language or library feature that might raise an exception, and we want to do something other than dump a stack trace to the terminal when the exception occurs. Maybe we're storing some user provided data in a dictionary and then looking for the name key in that dictionary

new_variable = user_dictionary["name"]

But what if the user didn't provide a dictionary with a name keyword? We know this will raise a KeyError, so we probably want to handle that occurrence. Maybe we want to let the user know how they need to modify their input.

try:
        new_variable = user_dictionary["name"]
except KeyError:
         print("There was some difficulty reading the name key, please make sure your data contains this key and an appropriate value")

Then we'll use whatever mechanism we need to give them another go.

This happens (as far as I'm aware) because when python's dictionary object can't match a key you've provided it raises a KeyError.

When designing more complex programs it's important to think about what your functions are trying to do, and where they might go wrong due to user input, the system they're on, network issues, changes to data or systems they interact with, etc.

If we have a program that pours water into a vessel (like a glass or kettle) we know it can't pour negative water, but if we're using integers to model the amount of water, or even the time of pouring, we couldn't use a negative int for either of those. There's nothing in python to stop you from entering "-10" as an input, but we don't this to occur. There's a lot of ways to handle this sort of input validation, but one is to raise an exception and handle it. We might even want to create our own exception class for NegativeInput.

Say we're then building a program to control an IoT kettle (Python's great for embedded devices like the Raspberry Pi!) We want to push a button on a phone app to boil the water in the kettle. That way we can start the boil after our shower and the water will be hot for our coffee or tea when we finish getting dressed.

We probably have a function to send a signal to the kettle to start boiling

kettle.start_boil()

Start boil just sends an on or off signal to our device, it's not very smart, but we don't want to boil in all circumstances. For instance, if the kettle is empty turning the element on may damage the device. Let's say we have a water level sensor in the kettle that reads between 0ml and 1,000ml.

Start boil can check that, and raise an exception if there's not enough water to safely boil. We could throw an error, but I really need my coffee in the morning and I don't like to wait! Instead let's have this exception take care of business itself, and pour in a glass of water using our previous program.

try:
        kettle.start_boil()
except WaterLevelError:
        gadget.pour_water(250)

#pretend we're within a kettle class here
def start_boil(self)
        if self.water_level < 100:
                raise WaterLevelError