Saturday, 22 February 2014

except: BadTitleError

Today's topic is all about exceptions.
Exceptions are errors that happen when something goes wrong in the execution of a python program. Having said that, I will not be talking about syntax errors in this post (because syntax errors and I are not on speaking terms).

Say, for example, you wanted to write a program that tells users what a certain number multiplied by 3 evaluates to. Here is what you may come up with:

def times_three(num):
        return num * 3

(Yes, the colors do not match the ones in Wing IDE. I got used to IDLE. Leave me alone.)

The function above works perfectly fine. However, to allow users to be able to use it to type in their favorite number to be multiplied by 3, you may decide to add a few lines to the program that allows for user input.

def times_three(num):
        return num * 3

num = input('Please enter your favorite number: ')

float(num)
print(times_three(num))

Doing this makes you a nice person but it also opens up the risk for your program to fail.
The program wants only to submit floats as an argument to times_three so if the user were to enter anything that is not a number then the program would crash.

The wise Python has foresaw these types of errors caused by improper object types, outrageous math operations, and trolls which can all destroy the self-esteem of a perfectly legitimate program. In order to prevent the program from just giving up and going home, we can raise exceptions.

In this particular example, a built-in ValueError is hit when running the program with a non-number input. We can notify the user when this error is detected by using the python try/except notation. That will simply try to run the section of code that may cause a problem (in this case converting the input into a float) and if it does not work properly we will raise the ValueError exception.

def times_three(num):
        return num * 3

num = input('Please enter your favorite number: ')

try:
        num = float(num)
        print(times_three(num))
except ValueError:
        print('Not a number. Go away :(')

Everything in the try block is attempted first. If it works, the program runs as is expected. If not, the ValueError is raised and the details of the error are shown to the user.
Doing this allows the program to terminate cleanly.

In addition to using built-in exceptions such as ValueError or ZeroDivisionError, python also allows you to write your own exceptions by defining them as a class and having them inherit from the all mighty Exception class. (I originally wanted this to be an example of that but then python flashed its built-inValueError card at me halfway through...)

In a more exotic program, there may be more than one risk with a certain block of code. In these scenarios, it is possible to have more than one except clause to catch different types of exceptions. The important thing to remember with those is that Python will go through them in the order that they are listed. This means that the except clauses should be put in the order of least specific to most specific in terms of the scope of the errors they catch.
I found Professor Heap's example to be very helpful when thinking of this. One thing that will always be certain is that if you want to catch all exceptions and use the all-inclusive Exception class then it should always be the last except clause.