c++ 标准异常类层次结构_Python学习点滴04 - 学会异常处理(1)

36a0982c191d479d9005b1e4c153e583.png

前言

我们在开发Python程序时经常会遇到一些错误(语法错误异常),尤其是程序代码发生异常(Exceptions)时,如果不能及时捕获异常和有效处理异常,则程序运行会被终止,有可能会造成相应的后果;相反如果能及时捕获异常并有效处理异常,则能大大提高程序的健壮性。因此学会Python异常处理还是很有必要的。

本文会比较系统地介绍Python异常的相关知识。

本文分享内容的目录如下:

0. 前言

1. 了解Python错误

-1.1 语法错误

-1.2 异常

-1.3 Traceback信息

2. 了解内置异常类

-2.1 内置异常类层次结构

-2.2 异常基类

-2.3 具体异常类

-2.4 OS异常类

-2.5 警告异常类

3. 创建自定义异常类

4. 如何捕获和处理程序中的异常

-4.1 基本try-except语句块

-4.2 多重异常try-except语句块(基本情形1)

-4.3 多重异常try-except语句块(基本情形2)

-4.4 带嵌套的try-except语句块

-4.5 try-except-else语句块

-4.6 try-except-finally语句块

-4.7 try-except-else-finally语句块

5. 如何抛出一个异常

-5.1 如何抛出一个内置异常

-5.2 如何抛出一个自定义异常

6. 如何让程序输出更详细的异常信息

-6.1 面临问题-使用捕获的异常类只能获取较少的异常信息

-6.2 解决办法-使用traceback模块可以获取更详细的异常信息

7. 结束语

注:限于篇幅,本文只介绍第0章至第3章,剩下的第4章-第7章在《Python学习点滴04 - 学会异常处理(2)》中介绍。

本文开发环境为:

- Windows 7 64-bit

- Python 3.8.5 64-bit。

- IDLE (Python 3.8.5 64-bit)


1. Python错误

目前python提供两种可区分的错误:语法错误异常

1.1 语法错误 Syntax errors

一、语法错误描述

语法错误(Syntax errors)又称解析错误(parsing errors),是在学习Python时最容易遇到的错误。

Python解析器(parser)在检测到代码语句存在语法错误时,程序根本就没执行,会在终端输出相关语法错误信息。

语法错误由于程序根本就没执行,所以并不会造成后果。

二、语法错误示例1

Python终端上输入代码语句时Python解析器输出语法错误信息的情形。

 >>> def myfun() print('Hello Python')   File "", line 1     def myfun() print('Hello Python')                 ^ SyntaxError: invalid syntax

二、语法错误示例2

运行syntaxerror.py文件(文件内容为def myfun() print('Hello Python'))时会在终端输出语法错误信息的情形。

 C:exception> python syntaxerror.py   File "syntaxerror.py", line 1     def myfun()  print('Hello Python')                  ^ SyntaxError: invalid syntax

三、语法错误说明

上述语法错误示例1和语法错误示例2实际上一回事,只是分别代表两种发生情形:一种是在Python终端上输入代码语句时Python解析器输出语法错误信息;一种是在运行syntaxerror.py文件会在终端输出语法错误信息。

上述输出的示例语法错误信息说明如下:

1、输出第1行:给出了导致语法错误信息的文件名和行号,便于语法错误的定位及后续修复。

2、输出第2行:给出了Python解析器检测到的第一个存在语法错误的代码语句。

3、输出第3行:有一个方向朝上的小箭头字符,指向第2行中检测到语法错误的代码语句中的具体位置。上述示例中,检测到语法错误是在该代码语句中 print() 函数之前少了个冒号:。

4、输出第4行:给出语法错误信息:SyntaxError,具体是:invalid syntax

1.2 异常 Exceptions

一、异常描述

即便Python程序中不存在语句错误,但在执行时,仍然可能会引发错误。

异常(Exceptions)是Python程序执行时检测到的错误,会在终端输出相应异常信息。

由于异常是程序执行时发生的,如果检测到异常但没有进行处理,或者处理不到位,那么程序就会终止执行,有可能会产生一些严重后果。因此一般而言,为了Python程序的健壮性而言,我们应该对程序中的异常进行捕获,然后给出有效的处理,防止程序执行终止。

二、异常示例1

Python终端上输入代码语句时Python解析器输出异常信息的情形。

 >>> 1/0 Traceback (most recent call last):   File "", line 1, in  ZeroDivisionError: division by zero

二、异常示例2

运行exception.py文件(文件内容为1/0)时会在终端输出异常信息的情形。

 C:exception> python exception.py Traceback (most recent call last):   File "c:/exception/exception.py", line 1, in      1/0 ZeroDivisionError: division by zero

三、异常说明

上述异常示例1和异常示例2实际上一回事,只是分别代表两种发生情形:一种是在Python终端上输入代码语句时Python解析器输出异常信息;一种是在运行exception.py文件时会在终端输出异常信息。

上述输出的示例异常信息分三个部分:

1、异常信息标志行:见输出第1行。

见到Traceback (most recent call last):就知道下面是具体的异常信息。

2、异常信息定位部分:见输出第1行与输出最后一行中间的几行。

2-1)、输出第2行给出了导致异常信息的文件名和行号,便于异常的定位及后续修复。

2-2)、输出第3行给出了Python解析器检测到的发生异常的代码语句/表达式。

3、异常信息类型内容部分:见输出最后一行。

给出异常信息的类型和内容。本示例异常类型为:ZeroDivisionError,异常内容是:division by zero(即被0除)。

1.3 Traceback信息

一、Traceback信息描述

Traceback信息异常堆栈信息(亦简称异常信息),当Python程序执行过程中发生异常时,程序就会抛出一个异常信息,如果程序没有指定相应的异常处理方法或异常处理方法不到位,Python就会使用Traceback来输出发生异常时代码执行栈的情况。

通过Traceback信息,开发者可以更好地对出现的异常进行定位和分析。

Traceback信息跟本文第1.2章节中异常信息是一回事,本节再介绍一个复杂些的示例。

二、Traceback信息示例

1、示例代码(traceback_test.py)

 def divfun(num1, num2):     return num1/num2  def main():     a = 10     b = 0     result = divfun(a, b)     print(result)  if __name__ == '__main__':     main()

2、执行traceback_test.py文件时会在终端输出Traceback信息的情形。

 C:exception> python traceback_test.py Traceback (most recent call last):   File "c:/exception/traceback_test.py", line 11, in      main()   File "c:/exception/traceback_test.py", line 7, in main     result = divfun(a, b)   File "c:/exception/traceback_test.py", line 2, in divfun     return num1/num2 ZeroDivisionError: division by zero    

三、Traceback信息说明

上述输出的示例的Traceback信息分三个部分:

1、异常信息标志行:见输出第1行。

见到Traceback (most recent call last):就知道下面是具体的异常信息。

2、异常信息定位部分:见输出第1行与输出最后一行中间的几行(输出第2行至第7行)。

2-1)、输出第2行和第3行给出了导致异常信息的文件名中代码第11行的main()语句。

2-2)、输出第4行和第5行给出了导致异常信息的文件名中代码第7行的result = divfun(a, b)语句。

2-3)、输出第6行和第7行给出了导致异常信息的文件名中代码第2行的return num1/num2语句。

通过上面逐层跟踪调用的方法,直至定位到本示例中真正导致异常信息的位置是位于文件的第2行(divfun()函数中的return num1/num2语句),即输出第6行和第7行的提示信息。

3、异常信息类型内容部分:见输出最后一行。

给出异常信息的类型和内容。本示例异常类型为:ZeroDivisionError,异常内容是:division by zero(即被0除)。


2. 了解内置异常类

2.1 内置异常类层次结构

Python内置异常的类层级结构如下:

 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

从上面类层次结构图中可以看出在Python中异常类命名的主要后缀有ErrorWarningExceptionExitIterationInterrupt

2.2 异常基类

下列异常主要被用作其他异常的基类。

e599b7cd9310978c3b01b7698d1d7b5f.png

异常基类

2.3 具体异常

以下异常属于经常被引发的异常。

2.3.1 AssertionError

一、描述:当 assert 语句失败时将被引发(即当assert后面的条件为假时,程序将终止并抛出一个AssertionError异常)。

二、示例

 >>> assert '北京' > '上海'  # 当assert后的条件为假时,程序终止并抛出一个AssertionError异常 >>> assert '北京' < '上海' Traceback (most recent call last):   File "", line 1, in      assert '北京' < '上海' AssertionError

2.3.2 AttributeError

一、描述:当试图访问的对象属性不存在时将被引发,会抛出AttributeError异常。

二、示例

 >>> a = 2 >>> a.add Traceback (most recent call last):   File "", line 1, in      a.add AttributeError: 'int' object has no attribute 'add'

2.3.3 ImportError

一、描述:当 import 语句尝试加载模块遇到麻烦时将被引发,会抛出ImportError异常。

二、示例

 >>> from math import abcd Traceback (most recent call last):   File "", line 1, in      from math import abcd ImportError: cannot import name 'abcd' from 'math' (unknown location)

2.3.4 IndexError

一、描述: 当序列抽取超出范围时将被引发。当在使用序列时,如果索引超出序列范围,则将被引发,会抛出IndexError异常。

二、示例

 >>> a = [1, 2, 3] >>> a[4] Traceback (most recent call last):   File "", line 1, in      a[4] IndexError: list index out of range

2.3.5 KeyError

一、描述: 当在现有字典(键集合)中找不到指定的关键字(Key值)时将被引发,会抛出KeyError异常。

二、示例

 >>> a = {'010':'北京', '021':'上海'} >>> a['010'] '北京' >>> a['022'] Traceback (most recent call last):   File "", line 1, in      a['022'] KeyError: '022'

2.3.6 NameError

一、描述: 当某个局部或全局名称未找到时将被引发,会抛出NameError异常。此异常仅用于非限定名称。

二、示例

 >>> abcd Traceback (most recent call last):   File "", line 1, in      abcd NameError: name 'abcd' is not defined

2.3.7 SyntaxError

一、描述: 当解析器遇到语法错误时将被引发,会抛出SyntaxError异常。

二、示例

 >>> print abcd SyntaxError: Missing parentheses in call to 'print'. Did you mean print(abcd)?

2.3.8 TypeError

一、描述: 当一个操作或函数被应用于类型不适当的对象时将被引发,会抛出TypeError异常。

二、示例

 >>> 1 + 'a' Traceback (most recent call last):   File "", line 1, in      1 + 'a' TypeError: unsupported operand type(s) for +: 'int' and 'str'

2.3.9 ValueError

一、描述: 当操作或函数接收到具有正确类型但值不适合的参数,并且情况不能用更精确的异常(例如 IndexError) 来描述时将被引发,会抛出ValueError异常。

二、示例

 >>> i = int(input('请输入一个整数:')) 请输入一个整数:a Traceback (most recent call last):   File "", line 1, in      i = int(input('请输入一个整数:')) ValueError: invalid literal for int() with base 10: 'a'

2.3.10 ZeroDivisionError

一、描述: 当除法或取余运算的第二个参数为零时将被引发,会抛出ZeroDivisionError异常。

二、示例

 >>> 1/0 Traceback (most recent call last):   File "", line 1, in      1/0 ZeroDivisionError: division by zero

2.4 OS异常类

下列异常均为 OSError 的子类,它们将根据系统错误代码被引发。

0e79423dc7069c7ca782879ce82f0026.png

OS异常类

2.5 警告异常类

下列异常被用作警告类别。

3fa9c60604b5403de19c3e87bb2cc695.png

警告异常类

3. 自定义异常类

开发者可以在Python自定义异常类。在Python中,所有异常必须为一个派生自 BaseException 类或其子类的实例。自定义异常类通常也需要继承 Exception 类或其子类。

下面示例自定义一个继承自 Exception 类的自定义异常类MyException

# 自定义异常类MyExceptionclass MyException(Exception):    def __init__(self, value):        self.value = value    def __str__(self):        return repr(self.value)

Python程序(custom_test.py)抛出的该自定义异常,如果不对该自定义异常进行有效处理,就会在终端显示Traceback信息,示例如下:

 Traceback (most recent call last):   File "c:/exception/custom_test.py", line 11, in      raise MyException('自定义异常') MyException: 自定义异常

上述输出的示例异常信息(Traceback信息)分三个部分:

1、异常信息标志行:见输出第1行。内容为Traceback (most recent call last):

2、异常信息定位部分:见输出第1行与输出最后一行中间的几行(输出第2行至第3行)。

2-1)、输出第2行给出了导致异常信息定位于:文件名中代码第11行。

2-2)、输出第3行给出了导致异常信息定位于:raise MyException('自定义异常')语句。

3、异常信息类型内容部分:见输出最后一行。

给出异常信息的类型和内容。本示例异常类型为:MyException,异常内容是:自定义异常


4. 如何捕获和处理程序中的异常

本章介绍如何捕获和处理程序中的异常的多种组合(基本try-except语句块两种情形的多重异常try-except语句块带嵌套的try-except语句块try-except-else语句块try-except-finally语句块try-except-else-finally语句块)。

详见《Python学习点滴04 - 学会异常处理(2)》第4章中介绍。


5. 如何抛出一个异常

本章介绍如何抛出一个内置异常、自定义异常。

详见《Python学习点滴04 - 学会异常处理(2)》第5章中介绍。


6. 如何让程序输出更详细的异常信息

本章介绍如何让程序输出更详细的异常信息(面临问题 - 使用捕获的异常类只能获取较少的异常信息、解决办法 - 使用traceback模块可以获取更详细的异常信息)。

详见《Python学习点滴04 - 学会异常处理(2)》第6章中介绍。


结束语

见《Python学习点滴04 - 学会异常处理(2)》最后一章中介绍。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值