Lesson 10
I am Your Father
Chapter 9: User-defined exceptions
Exception class hierarchy
We will end our core lessons by returning to object-oriented programming, more specifically on the topic of inheritance. Hopefully you still remember what that is!
Remember that in Lesson 9, I mentioned that Python exceptions are instances of the Exception
class.
I also showed you the class hierarchy for Exception
s in Lesson 9. Click on the following button if you wish to view them again.
BaseException
+-- SystemExit
+-- KeyboardInterrupt
+-- GeneratorExit
+-- Exception
+-- StopIteration
+-- StopAsyncIteration
+-- ArithmeticError
| +-- FloatingPointError
| +-- OverflowError
| +-- ZeroDivisionError
+-- AssertionError
+-- AttributeError
+-- BufferError
+-- EOFError
+-- ImportError
| +-- ModuleNotFoundError
+-- LookupError
| +-- IndexError
| +-- KeyError
+-- MemoryError
+-- NameError
| +-- UnboundLocalError
+-- OSError
| +-- BlockingIOError
| +-- ChildProcessError
| +-- ConnectionError
| | +-- BrokenPipeError
| | +-- ConnectionAbortedError
| | +-- ConnectionRefusedError
| | +-- ConnectionResetError
| +-- FileExistsError
| +-- FileNotFoundError
| +-- InterruptedError
| +-- IsADirectoryError
| +-- NotADirectoryError
| +-- PermissionError
| +-- ProcessLookupError
| +-- TimeoutError
+-- ReferenceError
+-- RuntimeError
| +-- NotImplementedError
| +-- RecursionError
+-- SyntaxError
| +-- IndentationError
| +-- TabError
+-- SystemError
+-- TypeError
+-- ValueError
| +-- UnicodeError
| +-- UnicodeDecodeError
| +-- UnicodeEncodeError
| +-- UnicodeTranslateError
+-- Warning
+-- DeprecationWarning
+-- PendingDeprecationWarning
+-- RuntimeWarning
+-- SyntaxWarning
+-- UserWarning
+-- FutureWarning
+-- ImportWarning
+-- UnicodeWarning
+-- BytesWarning
+-- ResourceWarning
Now that you understand inheritance, this hierarchy make even more sense: a ZeroDivisionError
is a subclass of ArithmeticError
, which in turn is a subclass of Exception
, which is a subclass of BaseException
(the root of all Python exceptions).
Order of Exceptions
There is one thing you need to be aware of when you have multiple except
clauses. The more general Exception
s should come after the more specific ones. If you run the code below, it should print out ZeroDivisionError
as expected.
try:
x = 5 / 0
except ZeroDivisionError:
print("ZeroDivisionError")
except ArithmeticError:
print("ArithmeticError")
except Exception:
print("Exception")
But what happens when you run the following code? Make a guess!
try:
x = 5 / 0
except Exception:
print("Exception")
except ArithmeticError:
print("ArithmeticError")
except ZeroDivisionError:
print("ZeroDivisionError")
When you run the code, it should print out only Exception
. This is because ZeroDivisionError
is a subclass of Exception
, so it is technically an instance of Exception
. Therefore, it will not check any further.
So beware of this subtlety! Of course, you should try NOT to have so many except
clauses in the first place, but keep each try... except
block as small and as specific as you can!