Python基础(9)——异常处理

1. 异常的定义

异常就是一个事件, 它影响了一个程序的正常运行,也可以理解为,程序运行到了一个不能处理的问题,然后产生的一个错误。

python中异常相关的关键字:try、except、else、finally、raise

2. 异常引发

当程序出现错误的时候,系统会自动引发异常,当然我们也可以允许程序自己引发异常,通过raise语句来抛出异常。

可以自己根据业务需求来抛出异常,例如程序中的数据、执行与既定的业务需求不符,这些异常系统无法自动抛出,需要我们根据需求来进行异常的抛出。

raise语句的使用方法:

  • 单独一个raise,可以引发当前上下文中捕获的异常,若上下文中无异常,则会引发RuntimeError
  • raise异常类,该句将引发指定异常类的默认实例。
  • raise异常对象,该句将引发指定的异常对象。

使用assert关键字引发异常:

l = [1, 2, 3, 4]

assert len(l) < 3, "列表长度超过3"
print("正常")
#======output=====
Traceback (most recent call last):
  File "F:/.../demo.py", line 3, in <module>
    assert len(l) < 3, "列表长度超过3"
AssertionError: 列表长度超过3

上述代码等价于:

l = [1, 2, 3, 4]

if len(l) > 3:
    raise AssertionError("列表长度超过3")
print("正常")

3. 异常处理

3.1 try…except捕获异常

try:
    # 业务处理代码
except Exception:
    # 对异常进行的处理

对异常进行处理后,代码还可以继续执行,如果不捕获异常,代码将直接结束运行。

try:
    l = []
    print(l[1])
except Exception:
    print("捕获了一个异常")
print("继续执行")
#======output======
捕获了一个异常
继续执行

有时候,我们需要对不同类型的异常进行不同的异常处理,python中可以通过使用多个except语句来进行不同类型的异常的捕获与处理。

try:
    l = []
    # int('fjdk') # 将这一行注释去掉,将会引发ValueError,被第二个Except块捕获
    print(l[1])
except IndexError:
    print("捕获了一个IndexError异常")
except ValueError:
    print("捕获了一个ValueError异常")
except Exception:
    print("捕获了其它异常")

通常在最后的except块中要捕获其它所有的异常,对其它异常进行统一处理,以保证程序能够顺利运行。

如果异常已经被前面的except块捕获,进入异常处理,后面的except块将不再执行。

当然我们也可以对一部分异常进行统一的处理,方式如下:

try:
    l = []
    int('fjdk')
    # print(l[1])
except (IndexError, ValueError): # 对多个不同的异常进行统一的处理
    print("捕获了一个IndexError异常或ValueError异常")
except Exception:
    print("捕获了其它异常")

3.2 try…except…else捕获异常

与上面的try...except语句相同,只是添加了一个else语句,在没有异常的情况下,else块中的代码将会被执行。

try:
    l = ['1', '2']
    print(l[1])
except (IndexError, ValueError):
    print("捕获了一个IndexError异常或ValueError异常")
except Exception:
    print("捕获了其它异常")
else:
    print("没有任何异常")
#=====output======
2
没有任何异常

3.3 try…except…finally捕获异常

在该结构中,无论try代码块中的代码是否正常执行,finally子句中的代码块总会被执行。在开发过程中通常用来释放资源。

下面是运行出现异常的例子:

l = [1, 2, 3]
try:
    print(l[5])
    print("没有出现异常")
except Exception as e:
    print("出现异常!")
finally:
    print("运行到finally")
#======output======
出现异常!
运行到finally

代码中无异常的例子:

l = [1, 2, 3]
try:
    print(l[1])
    print("没有出现异常")
except Exception as e:
    print("出现异常!")
finally:
    print("运行到finally")
#=======output=====
2
没有出现异常
运行到finally

在函数中如果使用finally要注意一些问题,应尽量避免在finally块中使用return语句、raise语句等。例如在finally语句中使用了return语句,将会出现以下情况:

def test():
    try:
        return True
    finally:
        return False

print(test())
#======output====
False

上述代码也就是不管怎么写,test函数的返回值都是False。因为不管try语句块中的代码是否执行,finally块中的语句都要执行,所以函数的返回值永远是False

4. 访问异常信息

4.1 异常对象访问异常信息

通过异常对象来访问异常信息:

  • args:返回异常的错误编号和错误信息
  • with_traceback():用于处理异常的传播轨迹,查看异常的传播轨迹可追踪异常触发的源头
import sys

try:
    f = open('test.txt')
    print("没有出现异常")
except Exception as e:
    print(e.args)  # 访问异常的错误信息
    print(e.with_traceback(sys.exc_info()[2]))  #用于处理异常的传播轨迹,查看异常的传播轨迹可追踪异常触发的源头,也可看到异常一路触发的轨迹。
    print("出现异常!")
finally:
    print("运行到finally")
#=======output=======
(2, 'No such file or directory')
[Errno 2] No such file or directory: 'test.txt'
出现异常!
运行到finally

sys.exec_info()

如果整个堆栈中都没有正在处理的异常,则返回三个None的元组;否则,返回值为(type, value, traceback)

其中type表示正在处理的异常类型;value表示异常实例;traceback表示一个回溯对象,该对象封装了最初发生异常时的调用堆栈。

4.2 使用traceback模块访问异常

该模块提供了一个标准接口来提取、格式化和打印 Python 程序的堆栈跟踪结果。

  1. print_tb():要传入traceback对象,可以从sys.exec_info()中获取。可以设置打印的异常的追溯限制条数,通过limit参数设置。

  2. print_exception():要传入etype,value,tb三个参数,正好对应sys.exec_info()函数返回的三个参数。同样也可以设置limit参数,另外还可以通过file参数指定输出信息的位置,可以输出到控制台,也可以输出到文件。

  3. print_exc():是print_exception()函数的简化。

  4. format_exc():格式化堆栈跟踪和异常信息,返回的是一个字符串。

import sys
import traceback
def func():
    return 2 / 0
def test():
    print("这是test函数")
    func()
try:
    test()
    print("没有出现异常")
except Exception as e:
    traceback.print_tb(sys.exc_info()[2], limit=1)
    # traceback.print_exception(*sys.exc_info(), limit=2)
    # traceback.print_exc(limit=2)
    print("出现异常!")
finally:
    print("运行到finally")
#======output====
这是test函数
出现异常!
运行到finally
  File "F:/.../demo.py", line 9, in <module>
    test()

#如果使用print_exception函数,打印结果如下:(使用print_exc函数打印结果相同)
这是test函数
出现异常!
运行到finally
Traceback (most recent call last):
  File "F:/.../demo.py", line 9, in <module>
    test()
  File "F:/.../demo.py", line 7, in test
    func()
ZeroDivisionError: division by zero

5. 自定义异常

自定义的异常必须继承Exception基类或者Exception的子类,自定义异常类时不需要实现过多的方法,根据自己的需求实现一下__init__()方法和__str__()方法即可。

l = [1, 2, 3, 4]
class ListTooLongError(Exception):
    def __init__(self, len_list):
        self.len_list = len_list

    def __str__(self):
        return "The length of list is {} which is too long.".format(self.len_list)

if len(l) > 3:
    raise ListTooLongError(len(l))
else:
    print("没有异常")
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值