我 的 个 人 主 页:👉👉 失心疯的个人主页 👈👈
入 门 教 程 推 荐 :👉👉 Python零基础入门教程合集 👈👈
虚 拟 环 境 搭 建 :👉👉 Python项目虚拟环境(超详细讲解) 👈👈
PyQt5 系 列 教 程:👉👉 Python GUI(PyQt5)文章合集 👈👈
Oracle数据库教程:👉👉 Oracle数据库文章合集 👈👈
优 质 资 源 下 载 :👉👉 资源下载合集 👈👈
手动抛出异常&自定义异常
- raise手动抛出异常
- raise语句
- assert 断言
- 概念
- 语法
- 自定义异常
raise手动抛出异常
raise语句
- 之前我们遇到的都是系统检测到一些特定的错误场景之后,自动的像外界抛出的异常,我们只需要使用
try...except
语句或with
语句解决这些异常就可以了 - 本节学习的是通过raise语句手动抛出指定类型的异常
- 应用场景
- 比如,我们写了一个库(模块),里面定义了很多函数
- 当外界用户调用库里面的函数时,传入的值不满足条件的时候,我们就可以抛出异常。用户可以通过
try...except
语句或with
语句来捕获这个异常来进行处理 - 大家可能在想,我们在函数内部直接用
try...except
语句对这种错误进行容错处理不就行了么- 1、我们的库可能会有很多人使用,每个人每种情况对这个异常的处理方法都可能不一样,如果在函数内用
try...except
语句处理,那就固定死了 - 2、有时候在函数内部并没有出现异常,根本无法用
try...except
语句进行捕获处理def set_age(age): print(f'张三的年龄是:{age}') # 比如别人调用这个函数的时候,我这里的age必须要大于0,那么他传入一个-10,函数内部并不会出现异常,也就无法通过`try...except`语句是进行捕获的
- 1、我们的库可能会有很多人使用,每个人每种情况对这个异常的处理方法都可能不一样,如果在函数内用
- 是不是考虑可以加上条件判断,不满足条件则通过
return
返回一个固定值呢?- 来一个简单的实例看一下
def test(a, b): if a <= b: return -1 return a - b # 这个函数调用的时候,要求a必须大于b,如果用return的方法,那当a<b的时候,返回一个-1 # 那到底是不满足条件返回的-1,还是计算结果是-1呢?这就容易让人产生误解
- 类似于诸多场景,我们就可以通过
raise
语句手动抛出异常,让用户知道出错了,并且可以捕获到这个异常,进行各自个性化的处理
- 语法
raise [Exception [, args [, traceback]]] # Exception # 引发的异常类或异常对象 # args # 异常的参数 # traceback # 异常的跟踪信息
- 引发内置异常
raise ValueError("这是一个ValueError异常")
- 引发自定义异常
class MyException(Exception): pass raise MyException("这是一个自定义异常")
- 示例
- 示例1:
- 如果只想知道是否抛出了一个异常,并不想去处理它,那么一个简单的
raise
语句就可以把它抛出def test(num): if num < 0: raise print(num) test(-10) # ========== 输出结果 ========== Traceback (most recent call last): File "E:\StudyCode\Python\14-异常处理\05-抛出异常.py", line 8, in <module> test(-10) File "E:\StudyCode\Python\14-异常处理\05-抛出异常.py", line 4, in test raise RuntimeError: No active exception to reraise Process finished with exit code 1
- 示例2:
raise
语句的唯一一个参数可以指定要被抛出的异常对象。它必须是一个异常的实例或者是异常的类- 我们可以通过这个指定的抛出的异常对象来捕获这个异常
def set_age(age): if age <= 0 or age > 200: raise ValueError print(age) try: set_age(-10) except ValueError as e: print('age参数传值超出范围', e) # ========== 输出结果 ========== # age参数传值超出范围
- 这里的输出结果可以看到仅仅只是打印了我们指定的字符串,错误对象e并没有输入任何内容
- 示例3:
raise
语句可以给异常对象添加参数,对这个异常进行说明,让使用者更加清晰是什么原因产生的异常def set_age(age): if age <= 0: raise ValueError('值小于0了!') elif age > 200: raise ValueError('值大于200了!') print(age) try: set_age(-10) except ValueError as e: print('age参数传值超出范围1:', e) try: set_age(310) except ValueError as e: print('age参数传值超出范围2:', e) # ========== 输出结果 ========== # age参数传值超出范围1: 值小于0了! # age参数传值超出范围2: 值大于200了!
assert 断言
概念
assert
断言用于判断一个表达式,在表达式条件为False
的时抛出AssertionError
异常- 断言可以在条件不满足程序运行的情况下直接返回错误,而不必等待程序运行后出现崩溃的情况的时候触发异常
语法
assert
语法# 不带参数 assert expression # 带参数 assert expression, arguments # assert # assert关键字 # expression # 表达式,表达式结果为True不抛出异常,结果为Fasle则抛出异常 # arguments # 参数,用于对异常的描述
- 等同于
# 不带参数 if not expression: raise AssertionError # 带参数 if not expression: raise AssertionError(arguments)
- 示例
- 示例1:不带参数
def set_age(age): assert age > 0 print(f'为张三设置的年龄是:{age}') set_age(-20) # ========== 输出结果 ========== Traceback (most recent call last): File "E:\StudyCode\Python\14-异常处理\06-assert断言.py", line 8, in <module> set_age(-20) File "E:\StudyCode\Python\14-异常处理\06-assert断言.py", line 3, in set_age assert age > 0 AssertionError
- 示例2:带参数
def set_age(age): assert age > 0, '年龄设置太小了!' print(f'为张三设置的年龄是:{age}') set_age(-20) # ========== 输出结果 ========== Traceback (most recent call last): File "E:\StudyCode\Python\14-异常处理\06-assert断言.py", line 8, in <module> set_age(-20) File "E:\StudyCode\Python\14-异常处理\06-assert断言.py", line 3, in set_age assert age > 0, '年龄设置太小了!' AssertionError: 年龄设置太小了!
自定义异常
-
前面我们所有手动抛出的异常类都是系统内置的
ValueError
,如果我们需要抛出一个我们自己异常类呢? -
示例
def set_age(age): if age <= 0: raise SxfError print(age) set_age(-10) # ========== 输出结果 ========== Traceback (most recent call last): File "E:\StudyCode\Python\14-异常处理\06-自定义异常.py", line 8, in <module> set_age(-10) File "E:\StudyCode\Python\14-异常处理\06-自定义异常.py", line 3, in set_age raise SxfError NameError: name 'SxfError' is not defined
-
这里输出结果提示我们名称错误:没有定义名称
SxfError
-
那么,我们先定义一个,这是一个异常类,所以我们需要定义一个类,再使用
class SxfError: pass def set_age(age): if age <= 0: raise SxfError print(age) set_age(-10) # ========== 输出结果 ========== Traceback (most recent call last): File "E:\StudyCode\Python\14-异常处理\06-自定义异常.py", line 11, in <module> set_age(-10) File "E:\StudyCode\Python\14-异常处理\06-自定义异常.py", line 6, in set_age raise SxfError TypeError: exceptions must derive from BaseException
-
定义类之后,依然报错了。提示我们类型错误:异常必须派生自
BaseException
-
我们回顾一下前面所学的异常,里面讲到了
BaseException
是所有内建异常的基类# BaseException # 所有内建异常的基类 # SystemExit # 由sys.exit()函数引发,当它不处理时,Python解释器退出 # KeyboardInterrupt # 当用户点击中断键时引发 # GeneratorExit # 当调用一种generator的close()方法时引发 # Exception # 所有内置的、非系统退出异常都是从该类派生的(所有自定义异常都应该继承自该类)
-
这里可以看到
SystemExit
是系统退出引发的异常类型,KeyboardInterrupt
是用户按键引发的异常类型,GeneratorExit
是关闭操作是引发的异常类型;而我们自定义的明显都不属于这几种操作,所以我们可以让自定义异常继承自Exception
这个异常类 -
Exception
类是继承自BaseException
类,自定义类再继承自Exception
类;那么,自定义类也就间接的继承自BaseException
类了 -
那我们尝试一下
class SxfError(Exception): pass def set_age(age): if age <= 0: raise SxfError print(age) set_age(-10) # ========== 输出结果 ========== Traceback (most recent call last): File "E:\StudyCode\Python\14-异常处理\06-自定义异常.py", line 11, in <module> set_age(-10) File "E:\StudyCode\Python\14-异常处理\06-自定义异常.py", line 6, in set_age raise SxfError __main__.SxfError
-
诶…好像成功了,下面抛出了异常,明显不再是前面的类型错误异常了,我们利用
try...except
语句捕获一下看看class SxfError(Exception): pass def set_age(age): if age <= 0: raise SxfError print(age) try: set_age(-10) except SxfError as e: print('出错啦!捕获到异常了!', e) # ========== 输出结果 ========== # 出错啦!捕获到异常了!
-
不错,异常捕获成功了!但是我们通过这个异常对象并没有拿到任何异常相关的信息
-
那么,我们可以通过传递参数来自定义异常的信息,以更准确地描述出现异常的原因和上下文。
-
在抛出异常时,可以将参数传递给异常类,供后续处理程序使用,那么我们在定义异常类的时候就需要添加
__init__()
方法来接收实例化对象时传递过来的实参了 -
示例代码:
class SxfError(Exception): def __init__(self, ErrorValue): self.ErrorValue = ErrorValue pass def set_age(age): if age <= 0: raise SxfError('值小于0了!') print(age) try: set_age(-10) except SxfError as e: print('出错啦!', e.ErrorValue) # ========== 输出结果 ========== # 出错啦! 值小于0了!
-
哈哈,这里我们通过对象的
ErrorValue
属性就可以拿到这个错误提示了,但是明显和我们使用内置的异常类不一样,内置的异常类只需要直接打印这个对象就可以输出这个异常提示了 -
回顾一下面向对象的内容,里面有一个
__str__
方法,在访问实例对象时会自动调用 -
关于面向对象
__str__
方法 -
那么,我们可以在类里面定义这个方法,并输出我们想要的内容
class SxfError(Exception): def __init__(self, ErrorValue, ErrorCode=None): self.ErrorValue = ErrorValue self.ErrorCode = ErrorCode def __str__(self): return str(self.ErrorValue) + ' ' + str(self.ErrorCode) def set_age(age): if age <= 0: raise SxfError('值小于0了!', 404) print(age) try: set_age(-10) except SxfError as e: print('出错啦!', e) # ========== 输出结果 ========== # 出错啦! 值小于0了! 404
-
这个就跟内置异常类型差不多啦!
-
其实,这个自定义异常就是一个自定义类,其他操作完全可以参照前面所学的面向对象相关内容