Python:exceptions
lastmod 2022-02-18created 2020-07-2615 edits
In Python, all exceptions must be instances of a class that derives from BaseException. In a try statement with an except clause that mentions a particular class, that clause also handles any exception classes derived from that class (but not exception classes from which it is derived). Two exception classes that are not related via subclassing are never equivalent, even if they have the same name.
How to use
-
raiseis the statement used to raise an error. -
try: ... except: ...is the most basic Exception handling statement.
raise from
- 8. Errors and Exceptions — Python 3.10.2 documentation
- (Python) raise vs. raise from e
- Stackoverflow - Python "raise from" usage
In a Python except block, another exception can be raised while handling an exception. If you want to show which exception the error raised during handling was derived from, use raise from.
import json
def load_json_key(data, key):
try:
result_dict = json.loads(data) # ValueError 발생할 수 있음.
except ValueError as e:
raise KeyError(key) from e
else:
return result_dict[key] # KeyError 발생 가능
load_json_key('{"foo": "bar"', 'foo')
I found the relevant explanation on StackOverflow. With the from clause, the __cause__ attribute of the raised exception is set, so the error message shows "directly caused by" and you can see which exception it was derived from. Without the from clause, the __context__ attribute is set instead of __cause__. That is why the error message shows a phrase like "during handling ~ happened" to tell you the situation in which the exception occurred.
If seeing all these messages is a hassle, use raise … from None. Only the first exception raised is printed in the error message.
List of exception
-
NotImplementedError: no implementation exists.
Handling Exceptions
import sys
try:
f = open('myfile.txt')
s = f.readline()
i = int(s.strip())
except IOError as e:
print "I/O error({0}): {1}".format(e.errno, e.strerror)
except ValueError:
print "Could not convert data to an integer."
except:
print "Unexpected error:", sys.exc_info()[0]
raise
User-defined Exceptions
class MyError(Exception):
def __init__(self, value):
self.value = value
def __str__(self):
return repr(self.value)
Exception hierarchy
The class hierarchy for built-in exceptions is:
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
My personal Exception rules
I follow these rules.
- Use built-in exceptions whenever possible.
- Write error messages that are as specific as possible.
- Do not use a sentence-ending period.
- Avoid line breaks where possible. (Summarize the error in one line where possible)
- BaseException is built-in. So custom exceptions inherit from Exception. Inheriting directly from a child class, per the inheritance hierarchy, is also OK.
Some cases:
- Wrong value (EmptyArgument, IllegalArgument, Encoding, Decoding, etc): ValueError
- Do not use SyntaxError for parsing errors. That error is limited to Python syntax.
- State-related errors (Exists, NotExists, NotReadyState, AlreadyState, IllegalState, etc) are all RuntimeError.
- Not found (NotFound) errors are also RuntimeError.
- However, if a file cannot be found, use FileNotFoundError.
- Not initialized (NotInitialized) errors are also RuntimeError.
- LookupError is used when a key or index (used on a mapping or sequence) is invalid.
See also
Favorite site
- Built-in Exceptions — Python 3.8.5 documentation
- 8. Errors and Exceptions
- Python course part 11. Exception Handling
- 4) Exception handling - Jump to Python 1
References
-
Jump_to_Python_-_Exception.pdf ↩