A Note on Python Try-Except Statements

TODO: write an introduction here

Firstly, it's almost never a good idea to "catch" the Exception class, and it is never a good idea to raise the Exception class directly. The point of using a try/except statement is that the program will be able to recover usefully from an error in the "except" suite. This means that any exceptions being raised should be specific enough that the caller knows for sure what happened (meaning we shouldn't raise Exception directly) and that they should only be caught at a point when something can be done about it (meaning we shouldn't use try/except statements at a level that's too high or low).

Consider this example of the __main__ file in a complicated application:

def main():
    do_stuff()
    do_more_stuff()
    do_last_stuff()
if __name__ == '__main__':
    try:
        main()
    except Exception:
        print('There was a problem, please restart the program.')

You can see that the try/except statement here will stop the program crashing if there is any exception raised by any function called by main(). However, while the program won't crash, you also can't recover in a useful way at this point. This technique may be useful in some applications, but I can't think of any other situation where it's even sort of a good idea to catch the Exception class.

Consider this counter-example that may be too fine-grained:

def example():
    the_list = get_list_from_user()
    the_index = get_index_from_user()
    try:
        print(str(the_list[the_index]))
    except IndexError:
        print('you gave an invalid index')

This situation could be fine. If you just want to print the item in the list or print the error message, this is probably the best way to do it. However, if you wanted to be able to retry the action, it should be more like this:

def example():
    the_list = get_list_from_user()
    the_index = get_index_from_user()
    print(str(the_list[the_index]))
printed_successfully = False
while not printed_successfully:
    try:
        example()
        printed_successfully = True
    except IndexError:
        print('That index number was invalid, please try again.')

This example is also a little weird because it's overly simple. But it shows the goal of a try/except statement: because the "while" loop catches a specific IndexError, in a specific function, the program knows exactly what went wrong and how to recover from it.