41

I come from Java where Exceptions and Errors are quite different things and they both derive from something called Throwable. In Java normally you should never try to catch an Error.

In Python though it seems the distinction is blurred.

So far after reading some docs and checking the hierarchy I have the following questions:

  1. There are syntax errors which of course cause your program not to be able to start at all. Right?

  2. "Errors detected during execution are called exceptions and are not unconditionally fatal" (per the tutorial). What does "fatal" mean here? Also, some objects like AttributeError are (by the above definition) actually exceptions even though they contain Error in their names, is that conclusion correct?

  3. Some classes derive from Exception but contain Error in their name. Isn't this confusing? But even so it means that Error in the name is in no way special, it's still an Exception. Or not... ?

  4. "All built-in, non-system-exiting exceptions are derived from [Exception]" (quote from here)
    So which ones are system-exiting exceptions and which ones are not? It is not immediately clear. All user-defined exceptions should also be derived from Exception. So basically as a beginner do I need to worry about anything else but Exception? Seems like not.

  5. Warnings also derive from Exception. So are warnings fatal or system-exiting or none of these?

  6. Where does the AssertionError fit into all of this? Is it fatal or system exiting?

  7. How does one know or specify that some Exception class represents fatal or system-exiting exception?

2
  • Correct, for your purposes there are just Exceptions. Commented Mar 16, 2020 at 15:37
  • 1
    Not sure how these things differ in Java, but in PHP "errors" are basically just something that produces an error message on screen/in the log, while exceptions are something which can be hierarchically handled via try..catch. In that sense, Python doesn't make that distinction. Every possible error is an exception and can be handled via try..except. Commented Mar 16, 2020 at 15:38

2 Answers 2

42
  1. Yes. SyntaxError isn't catchable except in cases of dynamically executed code (via eval/exec), because it occurs before the code is actually running.
  2. "Fatal" means "program dies regardless of what the code says"; that doesn't happen with exceptions in Python, they're all catchable. os._exit can forcibly kill the process, but it does so by bypassing the exception mechanism.
  3. There is no difference between exceptions and errors, so the nomenclature doesn't matter.
  4. System-exiting exceptions derive from BaseException, but not Exception. But they can be caught just like any other exception
  5. Warnings behave differently based on the warnings filter, and deriving from Exception means they're not in the "system-exiting" category
  6. AssertionError is just another Exception child class, so it's not "system exiting". It's just tied to the assert statement, which has special semantics.
  7. Things deriving from BaseException but not Exception (e.g. SystemExit, KeyboardInterrupt) are "not reasonable to catch" (or if you do catch them, it should almost always be to log/perform cleanup and rethrow them), everything else (derived from Exception as well) is "conditionally reasonable to catch". There is no other distinction.

To be clear, "system-exiting" is just a way of saying "things which except Exception: won't catch"; if no except blocks are involved, all exceptions (aside from warnings, which as noted, behave differently based on the warnings filter) are "system-exiting".

Sign up to request clarification or add additional context in comments.

5 Comments

Your answer is very good (the best on this page), and I've been rereading it multiple times. And still... this whole thing looks like a complete mess (compared to the situation in other languages). Messy hierarchy, messy terminology. It's all for historical reasons, I suppose. No base Error class even. Then some things called Errors which derive from Exception. Just weird. I know you can't do anything about it, I am leaving this comment here for other newcomers (to Python).
@peter.petrov: I think the main thing to keep in mind is that there is no separate category for "error". "Error" and "exception" are synonymous in Python. Aside from that, there's just looking at the exception hierarchy so you know which classes derive from BaseException without deriving from Exception, and remembering to never use bare except: (which would catch the BaseException stuff too).
I agree the hierarchy is a little off; MemoryError should not have fallen under Exception (there are rare cases where you want to catch it, but even when you do, you should be catching it specifically, same as KeyboardInterrupt, not catching it by accident with except Exception: that probably wasn't written to handle out of memory conditions). Similarly, OverflowError, intended for arithmetic that exceeds representation limits, is actually used primarily for "passed Python int too large to convert to C register width type"; it's not an ArithmeticError (the parent class) at all.
But most of the rest of it makes sense. It may not agree with more rigid nomenclature from languages that make distinctions between uncatchable terminal errors and catchable runtime exceptions, but that's because Python ensures nothing (aside from intentional os._exit calls or bugs that segfault the interpreter) is terminal ("We're all adults here" means if you really want to catch something you shouldn't, they'll let you). Python is simpler, which ends up being confusing to people expecting/used to a greater complexity.
Perhaps, given the "coming from Java" nature of the question, it's be prudent to say that java's Throwable is akin to python's BaseException, and java's RuntimeException is akin to python's Exception. There isn't quite the inbetween of Exception and Error, but java's Error is similar to python in that children of Throwable (py: BaseException) that aren't Exceptions (either lang) tend to be Errors. For python, children of BaseException are often treated similarly: system-level errors to not be disrupted.
2

Exceptions are designed for the programmer to know how to handle them such as outOfRange Once an exception arises the programmer has to decide how to handle it and the code can continue to operate relatively smoothly

On the other hand an error indicates a problem that the programmer could not foresee as an import error or a memory error Errors can still be addressed and ensure that the software continues to run but apparently not everything will be able to continue to work smoothly.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.