目录

异常

异常演示

异常类型

异常

什么是异常?

语法是正确的,但在运行它的时候,也有可能发生错误,这种运行期检测到的错误被称为异常。

为什么要对异常进行处理?

当我们预知当代码运行期间可能发生的错误,就可以在代码中对可能发生的错误进行处理。比如,代码中要求用户输入一个数字作为一个公式的分母,但用户输入了一个0或者输入了一个字母,就会导致异常发生。对于这种可预见的异常进行的处理就叫异常处理。

当我们认为某些代码可能会出错时,就可以用try来运行这段代码

python本身的bug python常见bug_异常

  1. 如果执行出错,则后续代码不会继续执行,而是直接跳转至错误处理代码,即except语句块,执行完except后,如果finally语句块,则执行finally语句块。如果执行没有出错,会绕过所有except语句块。
  2. 有一个可选的 else 子句,必须放在所有的 except 子句之后。else 子句将在 try 子句没有发生任何异常的时候执行。
  3. finally 语句无论是否发生异常都将执行最后的代码。
  4. 如果一个异常没有与任何的 except 匹配,那么这个异常将会传递给上层的 try 中,直到被python解释器捕获。(也就是说异常处理并不仅仅处理那些直接发生在 try 子句中的异常,而且还能处理子句中调用的函数(甚至间接调用的函数)里抛出的异常。)

异常演示

下边这个代码

try:
    print('try...\n')
    a = int(input())
    r = 100 / a
    print('result:', r)
except ValueError as e:
    print('ValueError:',e)
else:
    print('no error!')
finally:
    print('finally...')
print('END')

当输入12时,没有异常,执行了else语句和finally语句。

python本身的bug python常见bug_exception_02

当输入一个字母的时候(比如输入r),则触发了异常,跳过else语句,执行finally语句。

python本身的bug python常见bug_ico_03

此外,一个except子句可以同时处理多个异常,这些异常将被放在一个括号里成为一个元组。

except (RuntimeError, TypeError, NameError):
    pass

异常类型

所有的错误类型都继承自BaseException,所以在使用except时需要注意的是,它不但捕获该类型的错误,还把其子类也“一网打尽”。

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 类,可以直接继承,或者间接继承。

 记录和抛出错误

如果对异常不做处理只做记录的话,python内置的logging模块可以非常容易地记录错误信息,程序打印完错误信息后会继续执行,并正常退出。

raise语句抛出一个错误的实例。

语法:raise <Error_Type>

有时候,一个函数如果捕获到一种错误,但是不知道如何处理的话,可以将这个错误抛出,也就是抛给上级函数处理。

比如;

def foo(s):
    n = int(s)
    if n==0:
        raise ValueError('invalid value: %s' % s)
    return 10 / n

def bar():
    try:
        foo('0')
    except ValueError as e:
        print('ValueError!')
        raise

bar()

捕获错误目的只是记录一下,便于后续追踪。但是,由于当前函数不知道应该怎么处理该错误,所以,最恰当的方式是继续往上抛,让顶层调用者去处理。