Python异常处理机制

一、异常处理机制

和 其他编程语言一样,Python 也提供了处理异常的机制。
Python 异常处理机制会涉及 try、except、else、finally 这 4 个关键字和 raise 语句 。

1、错误和异常

Python 编写程序时遇到的异常可大致分为 2 类:语法错误和运行时异常。

(1)错误

语法错误:也叫做解析错误,就是解析代码时出现的错误。

当代码不符合 Python 语法规则时,Python解释器在解析时就会报出 SyntaxError 语法错误,与此同时还会明确指出最早探测到错误的语句,并以调用栈的形式显示出来。

示例代码如下:

print('Hello world)

# 错误信息:
File "D:\JQWS\PythonWS\demo1\dir5\demo1.py", line 3
    print('Hello world)
          ^
SyntaxError: unterminated string literal (detected at line 3)  

(2)运行时异常

运行时异常:即程序在语法上都是正确的,但在运行时发生了错误。把在运行期检测到的错误被称为异常(Exceptions)。

示例代码如下:

a = 1 / 0
print(a)

# 错误信息:
Traceback (most recent call last):
  File "D:\JQWS\PythonWS\demo1\dir5\demo1.py", line 5, in <module>
    a = 1/0
        ~^~
ZeroDivisionError: division by zero

常见的运行时异常如下:

  • NameError:尝试访问一个未声明的变量时,引发此异常
  • IndexError :索引超出序列范围会引发此异常
  • KeyError:字典中查找一个不存在的关键字时引发此异常
  • TypeError:不同类型数据之间的无效操作
  • ZeroDivisionError:除法运算中除数为 0 引发此异常
  • AttributeError:当试图访问的对象属性不存在时抛出的异常

2、异常处理

开发者可以使用异常处理全面地控制自己的程序。异常处理不仅仅能够管理正常的流程运行,还能够在程序出错时对程序进行必的处理。大大提高了程序的健壮性和人机交互的友好性。

2.1 try/except

使用 try except语句捕获并处理异常,其基本语法格式如下:

try:
    可能产生异常的代码块
except [ (Error1, Error2, ... ) [as e] ]:
    处理异常的代码块1
except [ (Error3, Error4, ... ) [as e] ]:
    处理异常的代码块2
except  [Exception]:
    处理其它异常
  • 一个 try 语句可能包含多个except子句,分别来处理不同的特定的异常。
  • 一个except子句可以同时处理一个或者多个异常,这些异常将被放在一个括号里成为一个元组。

如果在执行 try 子句的过程中发生了异常,那么 try 子句余下的部分将被忽略。Python 解释器会寻找能处理该异常对象的 except 块,如果异常的类型和 except 之后的名称相符,那么对应的 except 子句将被执行。

如果一个异常没有与任何的 except 匹配,那么这个异常将会传递给上层的 try 中。如果 Python 解释器找不到处理异常的 except 块,则程序运行终止,Python 解释器也将退出。

示例代码如下:

try:
    a = int(input("输入被除数:"))
    b = int(input("输入除数:"))
    c = a / b
    print("您输入的两个数相除的结果是:", c)
except (ValueError, ArithmeticError):
    print("程序发生了数字格式异常、算术异常之一")
except ZeroDivisionError:
    print("除数不能为0")
except Exception as e:
    # 访问异常的错误编号和详细信息
    print(e.args)
    print(str(e))
    print(repr(e))

print("程序继续向下运行")

2.2 try/except…else

try/except 语句还有一个可选的 else 子句,在except 子句之后添加一个 else 子句,即try except else结构。

其基本语法格式如下:

try:
    可能产生异常的代码块
except [ (Error1, Error2, ... ) [as e] ]:
    处理异常的代码块1
except [ (Error3, Error4, ... ) [as e] ]:
    处理异常的代码块2
except  [Exception]:
    处理其它异常
else:
    try没有发生任何异常的时,才会执行的语句
  • else 子句含义:只有在 try 子句没有发生任何异常的时候执行 else 块中的代码。否则不执行它。else 子句必须放在所有的 except 子句之后。

示例代码如下:

try:
    a = int(input("输入被除数:"))
    b = int(input("输入除数:"))
    c = a / b
    print("您输入的两个数相除的结果是:", c)
except (ValueError, ArithmeticError):
    print("程序发生了数字格式异常、算术异常之一")
except ZeroDivisionError:
    print("除数不能为0")
except Exception as e:
    # 访问异常的错误编号和详细信息
    print(e.args)
    print(str(e))
    print(repr(e))
else:
    print('没有出现任何异常')

print("程序继续向下运行")

2.3 try-finally

try-finally 语句基本语法格式如下:

try:
    可能产生异常的代码块
except [ (Error1, Error2, ... ) [as e] ]:
    处理异常的代码块1
except [ (Error3, Error4, ... ) [as e] ]:
    处理异常的代码块2
except  [Exception]:
    处理其它异常
else:
    try没有发生任何异常的时,才会执行的语句
finally:
    无论 try 块是否发生异常都会执行的语句

在整个异常处理机制中,finally 语句的功能是:无论 try 块是否发生异常,最终都要进入 finally 语句,并执行其中的代码块。

注意:和 else 语句不同,finally 只要求和 try 搭配使用,而至于该结构中是否包含 except 以及 else,对于 finally 不是必须的(else 必须和 try except 搭配使用)。

示例代码如下:

try:
    a = int(input("请输入 a 的值:"))
    print(20/a)
except:
    print("发生异常!")
else:
    print("执行 else 块中的代码")   
finally :
    print("执行 finally 块中的代码")

2.4 抛出异常

Python 使用 raise 语句抛出一个指定的异常。

raise语法格式如下:

raise [exceptionName [(reason)]]

也就是说,raise 语句有如下三种常用的用法:

  • raise:单独一个 raise。该语句引发当前上下文中捕获的异常(比如在 except 块中),或默认引发 RuntimeError 异常。
  • raise 异常类名称:raise 后带一个异常类名称,表示引发执行类型的异常。
  • raise 异常类名称(描述信息):在引发指定类型的异常的同时,附带异常的描述信息。

示例代码如下:

try:
    a = input("输入被除数:")
    # 判断用户输入的是否为数字
    if (not a.isdigit()):
        # raise
        # raise ValueError()
        raise ValueError("a 必须是数字")

    b = int(input("输入除数:"))
    c = a / b
    print("您输入的两个数相除的结果是:", c)
except ValueError as e:
    print("引发异常:", repr(e))
except [RuntimeError, TypeError]:
    raise
except Exception as e:
    # 访问异常的错误编号和详细信息
    print(e.args)
    print(str(e))
    print(repr(e))
except:
    print("未知异常")

3、获取异常详情

捕获异常时,有 2 种方式可获得更多的异常信息,分别是:

  • 使用 sys 模块中的 exc_info 方法;
  • 使用 traceback 模块中的相关函数。

3.1 使用 sys 模块

exc_info() 方法会将当前的异常信息以元组的形式返回。

该元组中包含 3 个元素,分别是:

  • type:异常类型的名称,它是 BaseException 的子类。
  • value:捕获到的异常实例。
  • traceback:是一个 traceback 对象。

示例代码如下:

# 引入 sys 模块
import sys
try:
    x = int(input("请输入一个被除数:"))
    print("30除以",x,"等于",30/x)
except:
    print(sys.exc_info())
    print("其他异常...")

在这里插入图片描述

我们可以使用 traceback 模块的方法,查看结果中第三元素包含的内容(raceback 对象)。

调用 traceback 模块中的 print_tb 方法,并将 sys.exc_info() 输出的 traceback 对象作为参数参入。

示例代码如下:

# 引入 sys 模块
import sys
# 引入 traceback模块
import traceback

try:
    x = int(input("请输入一个被除数:"))
    print("30除以", x, "等于", 30 / x)
except:
    # print(sys.exc_info())
    traceback.print_tb(sys.exc_info()[2])
    print("其他异常...")

Python异常处理机制_第1张图片

3.2 traceback 模块

使用 traceback 模块,该模块可以用来查看异常的传播轨迹,追踪异常触发的源头。

traceback中的函数有很多,上面使用了 traceback.print_tb()函数,这里再使用一个 traceback.print_exc()函数。

traceback.print_exc():将异常传播轨迹信息输出到控制台或指定文件中。

print_exc() 函数的完整形式是:

print_exception(etype, value, tb[,limit[, file]])

参数说明:

  1. etype:指定异常类型;
  2. value:指定异常值;
  3. tb:指定异常的traceback 信息;
  4. limit:用于限制显示异常传播的层数。如果不设置 limit 参数,则默认全部显示。
  5. file:指定将异常传播轨迹信息输出到指定文件中。如果不指定该参数,则默认输出到控制台。

我们可以使用 except 块捕获异常,并在其中打印异常传播信息,包括把它输出到文件中。例如如下程序:

# 导入 trackback模块
import traceback

class SelfException(Exception):
    pass

def main():
    firstMethod()

def firstMethod():
    secondMethod()

def secondMethod():
    thirdMethod()

def thirdMethod():
    raise SelfException("自定义异常信息")

try:
    main()
except:
    # 捕捉异常,并将异常传播信息输出控制台
    traceback.print_exc()
    # 捕捉异常,并将异常传播信息输出指定文件中
    traceback.print_exc(file=open('log.txt', 'a'))

Python异常处理机制_第2张图片

三、自定义异常类

用户自定义异常:创建一个新的异常类。该类继承 Exception 类,可以直接继承,或者间接继承。

大多数的异常的名字都以"Error"结尾,我们自定义异常类的命名推荐也使用它结尾。

示例代码如下:

# 自定义异常类
class MyError(Exception):
    def __init__(self, value):
        self.value = value

    def __str__(self):
        return repr(self.value)


try:
    # 测试:抛出异常
    raise MyError(2 * 2)
except MyError as e:
    print('自定义异常:', e.value)

当创建一个模块有可能抛出多种不同的异常时,通常的做法是为这个包建立一个基础异常类,然后基于这个基础类为不同的错误情况创建不同的子类。

四、assert(断言)

Python assert 语句,又称断言语句,它用于判断一个表达式,在表达式条件为 false 的时候触发异常。

该语句的语法结构为:

assert 表达式

  • 如果值为真,则程序可以继续往下执行;反之,Python 解释器会触发异常。

assert 语句的执行流程可以用 if 判断语句来表示,代码如下:

if 表达式==True:
    程序继续执行
else:
    程序报 AssertionError 错误

示例代码如下:

x = int(input("请输入一个数:"))
# 断言:数是否位于正常范围内
assert 0 <= x <= 100
# 只有当 x 位于 [0,100]范围内,程序才会继续执行,否则会报错:AssertionError
print("x=", x)

Python异常处理机制_第3张图片

– 求知若饥,虚心若愚。

你可能感兴趣的:(Python,Python异常处理机制)