Exception hierarchy
We've already encountered many of the most common built-in exceptions, and you'll probably encounter the rest over the course of your regular Python development. As we noticed above, most exceptions are subclasses of the Exception class. But this is not true of all exceptions. Exception itself actually inherits from a class called BaseException (In fact, all exceptions must extend the BaseException class or one of its subclasses). There are two key exceptions, SystemExit and KeyboardInterrupt, that derive directly from BaseException instead of Exception.
SystemExit is an exception that is raised whenever the program exits naturally, typically because we called the sys.exit function somewhere in our code (for example, because the user selected an exit menu item, clicked the "close" button on a window, or entered a command to shut down a server). The exception is designed to allow us to clean up code before the program ultimately exits, so we generally don't need to handle...