Python : Exception

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
  • exception BaseException

The base class for all built-in exceptions. It is not meant to be directly inherited by user-defined classes (for that, use Exception).

  • exception Exception

All built-in, non-system-exiting exceptions are derived from this class. All user-defined exceptions should also be derived from this class.

for example

  • 1
>>> MyBad = 'oops'

def stuff( ):
    raise MyBad

>>> try:
        stuff( )
>>> except MyBad:
        print('got it')
...
TypeError: catching classes that do not inherit from BaseException is not allowed

asically, MyBad is not an exception, and the raise statement can only be used with exceptions.
To make MyBad an exception, you must make it extend a subclass of Exception.

  • 2
class MyBad(Exception):
    pass

def stuff( ):
    raise MyBad

>>> try:
        stuff( )
>>> except MyBad:
        print('got it')
...
got it
  • 3
class MyBad(Exception):
    def __init__(self, message):
        super().__init__()
        self.message = message

def stuff(message):
    raise MyBad(message)

>>> try:
        stuff("Your bad")
    except MyBad as error:
        print('got it (message: {})'.format(error.message))
...
got it (message: your bad)

__context__ v.s. __cause__ v.s. __traceback__

This PEP proposes three standard attributes on exception instances: the __context__ attribute for implicitly chained exceptions, the __cause__ attribute for explicitly chained exceptions, and the __traceback__ attribute for the traceback. A new raise … from statement sets the __cause__ attribute.

  • the name of __cause__ and __context__

For an explicitly chained exception, this PEP suggests __cause__ because of its specific meaning. For an implicitly chained exception, this PEP proposes the name __context__ because the intended meaning is more specific than temporal precedence but less specific than causation: an exception occurs in the context of handling another exception.

  • associated value

Except where mentioned, they have an “associated value” indicating the detailed cause of the error. This may be a string or a tuple of several items of information (e.g., an error code and a string explaining the code). The associated value is usually passed as arguments to the exception class’s constructor.

  • __context__

When raising (or re-raising) an exception in an except or finally clause __context__ is automatically set to the last exception caught; if the new exception is not handled the traceback that is eventually displayed will include the originating exception(s) and the final exception.

>>> try:
...   print(1/0)
... except:
...   raise RuntimeError('Something bad happened')
... 
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
ZeroDivisionError: division by zero

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<stdin>", line 4, in <module>
RuntimeError: Something bad happened
  • __cause__

When raising a new exception (rather than using a bare raise
to re-raise the exception currently being handled), the implicit exception context can be supplemented with an explicit cause by using from with raise.

raise new_exc from original_exc

The expression following from must be an exception or None. It will be set as __cause__ on the raised exception. Setting __cause__ also implicitly sets the __suppress_context__ attribute to True, so that using
raise new_exc from None
effectively replaces the old exception with the new one for display purposes.

>>> try:
...   print(1/0)
... except Exception as exc:
...   raise RuntimeError('something bad happened') from exc
... 
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
ZeroDivisionError: division by zero

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "<stdin>", line 4, in <module>
RuntimeError: something bad happened

The from clause is used for exception chaining: if given, the second expression must be another exception class or instance, which will then be attached to the raised exception as the __cause__ attribute (which is writable). If the raised exception is not handled, both exceptions will be printed.

  • raise exc from None
>>> try:
...     print(1 / 0)
... except:
...     raise RuntimeError("Something bad happened") from None
...
Traceback (most recent call last):
  File "<stdin>", line 4, in <module>
RuntimeError: Something bad happened
  • Exception chaining can be explicitly suppressed by specifying None in the from clause.
  • The default traceback display code shows these chained exceptions in addition to the traceback for the exception itself. An explicitly chained exception in __cause__ is always shown when present. An implicitly chained exception in __context__ is shown only if __cause__ is None and __suppress_context__ is false.
  • In either case, the exception itself is always shown after any chained exceptions so that the final line of the traceback always shows the last exception that was raised.

read more: Built-in Exceptions

def main(filename):
    file = open(filename)       # oops, forgot the 'w'
        try:
            try:
                compute()
            except Exception, exc:
                log(file, exc)
        finally:
            file.clos()         # oops, misspelled 'close'

def compute():
    1/0

def log(file, exc):
    try:
        print >>file, exc       # oops, file is not writable
    except:
        display(exc)

def display(exc):
    print ex                    # oops, misspelled 'exc'
  • Calling main() with the name of an existing file will trigger four exceptions. The ultimate result will be an AttributeError due to the misspelling of clos, whose __context__ points to a NameError due to the misspelling of ex, whose __context__ points to an IOError due to the file being read-only, whose __context__ points to a ZeroDivisionError, whose __context__ attribute is None.
  • Each thread has an exception context initially set to None.

The __cause__ attribute on exception objects is always initialized to None. It is set by a new form of the raise statement:

raise EXCEPTION from CAUSE

which is equivalent to:

exc = EXCEPTION
exc.__cause__ = CAUSE
raise exc
def print_chain(exc):
    if exc.__cause__:
        print_chain(exc.__cause__)
        print '\nThe above exception was the direct cause...'
    elif exc.__context__:
        print_chain(exc.__context__)
        print '\nDuring handling of the above exception, ...'
    print_exc(exc)
    原文作者:庞贝船长
    原文地址: https://www.jianshu.com/p/39e4f4210d5b
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞