Join Barron Stone for an in-depth discussion in this video Custom errors, part of Programming Foundations: Real-World Examples.
- With the breaker back on, I can try the dishwasher again. - Barron we have another problem. The dishwasher is spewing water everywhere. - Uh oh, well this is a new type of issue. I know how to handle electrical problems, but I don't know how to stop an out of control dishwasher. When handling errors it's very important that I consider the type of error that's occurred. If it's an error I'm able to handle, then I can take some appropriate action to deal with it. On the other hand, there may be types of errors that I'm not prepared to handle, like a raging dishwasher. In that case, I can pass the error information on to somebody else that is able to handle it.
I need to call a plumber. Many programming languages will include built in error types for many commonly incurring exceptions. Here in the console window, if I try to divide by zero, which you should never do, then Python will raise an exception of the type zero division error. Another type of exception that Python will raise is the name error exception which occurs if you try to access a variable or function that doesn't exist. Other interpreted languages, like Matlab, can also encounter this type of problem.
If I type spam, it'll raise a name error exception because the name spam has not been defined within my program. As a final example, if I try to add a string to an integer by typing spam plus one, Python will raise a type error exception because those two different types of objects cannot be added together. Those are just some of the built in error types that Python can raise for common exceptions. As you use additional modules and packages in your programs, you may encounter other specialized types of errors that are specific to the functionality of those modules.
Python even allows you to create your own custom error types be defining your own class that inherits from the generic exception class. When using a try except block, we can create multiple except statements which will selectively execute depending on the type of exception that occurs. To demonstrate that, I'll use the script called start 1103 custom errors from the exercise files. In this example, I've created two custom error classes on my own to represent an electrical error and a plumbing error. Both of my classes inherit from the generic exception class and I've defined their own init and str methods which override the inherited versions of those methods from the exception class.
The new init method for each of my error classes has an input parameter for the device that caused the error and for the specific problem. It stores those values internally as variables. The str method uses those variables to assemble and return a string that describes the error. When I call the print method on the Python object, it'll use the str method to retrieve the string to print. Below those two class definitions, I've also defined a simple function named cause error which I use to manually raise an error in my program.
If I pass the input string electrical for the error type, it'll raise an electrical error that the circuit breaker is overloaded. Of I can pass in the string, plumbing and it will raise an plumbing error that the dishwasher is spraying water everywhere. Now to use these new custom error classes, I'll start by creating a try statement containing the cause error function and I'll set it to raise an electrical error. After that, I'll create two except statements to handle each type of error. For the first one I'll type except electrical error as e colon, and this line will only catch exceptions that are electrical errors.
And it will bind that electrical error object, which was created for the exception to the variable name e so I can use it in the handling code. For example, if I put print e inside of the except block, it'll print out the error string I created with the str method in the electrical error class. Since I know how to handle electrical problems, I'll handle this error by fixing it myself. Now that I've created an except block to handle electrical errors, I need to do the same thing to handle plumbing errors. I'll just copy and paste that block of code, change electrical error to plumbing error, and since I don't know how to fix plumbing errors myself, I'll call the plumber instead.
When I run this script, the cause error function in the try block will generate an electrical problem so the except statement for electrical errors will be executed and I'll fix the problem myself. You can see here in the shell that the circuit breaker was overloaded and that I fixed it myself. If I change the problem to plumbing, and run that script again, the except statement for plumbing errors is executed and I'll call a professional plumber for help. Great, I have electrical and plumbing issues locked down, but there are a lot of other things that can go wrong around the house.
I'm going to modify the cause error function to raise a generic exception if something other than an electrical or plumbing problem occurs. To do that I'll just add in else statement at the end, and raise an exception with the message, generic household problem. Now, if I use the cause error function to cause another type of error, perhaps the grass in my yard is dying, and then run the script, it'll crash, because the try except block was only built to handle electrical and plumbing problems.
When we do not catch and handle an exception, then Python with automatically raise it up to the next level in the program. It does that to allow higher level functions and opportunity to handle the error. However, I'm not using sub functions in this script so when the error gets raised, it causes the program to crash. This exception was a generic type of exception and the message states that it was a generic household problem. I can modify the try except block to handle all types of exceptions by adding a final default except statement that doesn't specify a specific type of error.
This will catch anything that slips past the previous except statements for electrical and plumbing errors. I'll handle all of these other household problems by calling the landlord. Now when I execute this script, it'll raise a generic exception but the default except statement will catch it and I'll call the landlord to let them know about the problem. Error handling is one of the most important and overlooked aspects of programming. As a programmer, you spend a lot of time fighting with syntax errors as you learn your new language, but once you get past those struggles, it's important that you don't just assume that program will run like you want it to.
Remember, error handling is about more than just making sure your code is correct, it's about making sure your code does the right thing when it deals with the unpredictable outside world. When you put your code in the hands of other users they will almost certainly find a way to break it. The two situations that you want to avoid are having an error occur that you didn't realize exists, or recognizing that there's a problem, but you have no idea what it is or what happened. By implementing good error handling, you can catch these problems, deal with them appropriately and mitigate the impact of unpredictable users.
- Reusing functions
- Local vs. global variables
- Creating and naming custom objects
- Class inheritance
- Modules and packages
- Multidimensional lists and tuples
- Queues and stacks
- Creating and combining sets
- Storing data in dictionaries
- If/else and switch statements
- For vs. while loops
- Error handling
- Polling and event-driven programming