当检测到⼀个错误时,解释器就无法继续执行了,反而出现了⼀些错误的提示,这就是所谓的"异常"。
Python 提供了两个非常重要的功能来处理程序在运行中出现的异常和错误。我们可以使用该功能来调试程序。
什么是异常:
- 异常是一个事件,该事件会在程序执行过程中发生,影响了程序的正常执行;
- 一般情况下,在 Python 无法正常处理程序时会发生一个异常;
- 异常是 Python 对象,表示一个错误(bug)
- 当 Python 脚本发生异常时我们需要捕获处理,否则程序不会继续执行。
异常语法:
try:
程序正常执行此块代码
except:
错误时执行此块代码并抛出异常
常见异常:
简易示例:
try:
# 程序正常执行
num = input('请输入:')
number = float(num)
print(number)
except:
# 当程序达到某个条件时:
number = 1
print(number)
解析: 上述示例,虽然不报错,但无法记录具体的异常种类,若需记录具体的异常种类,则需捕获该具体异常。语法如下:
"""语法:
try:
pass
except 当前异常对象 as e: # e = 当前异常对象
print(e)
"""
先来看一下,不捕获异常的写法:程序无法继续执行;
li = [1, 2, 3, 4, 5]
print(li[6]) # 报错:IndexError: list index out of range
a = 1
b = 0
c = a / b
print(c) # 报错:ZeroDivisionError: division by zero
print(int('a')) # 报错:ValueError: invalid literal for int() with base 10: 'a'
再来看一下捕获异常:能够抛出具体的异常,且不影响程序执行;
try - except:
try:
li = [1, 2, 3, 4, 5]
print(li[6])
# except IndexError as e: # e = IndexError,这种方法仅能捕获这一种异常类型
# print(e)
except Exception as e: # 通过共同的父类Exception捕获输出
# 类的实例对象调用__class__属性时会指向该实例对应的类,而后再调用__name__,输出该实例对应的类的类名
print(e.__class__.__name__, ":", e, '---') # IndexError : list index out of range ---
try - except - else:
- 如果抛出异常,执行 except 内容代码
- 如果正常执行,程序执行 else 内部代码
try:
li = [1, 2, 3, 4, 5]
print(li[8])
# 如果抛出异常,执行except内部代码
except Exception as e:
print(e.__class__.__name__, ":", e, '糟糕,报错了。')
# 如果正常执行,程序执行else内部代码
else:
print('哈哈哈')
输出结果:
IndexError : list index out of range 糟糕,报错了。
try - except - finally:
不管程序有无发生异常,都会执行 finally 内部代码;
try:
li = [1, 2, 3, 4, 5]
# 如果抛出异常,执行 except 内部代码
except Exception as e:
print(e.__class__.__name__, ":", e, '。')
# 如果正常执行,程序执行 else 内部代码
else:
print('很晚了,该睡觉了。')
# 不管程序有无发生异常,都会执行 finally 内部的代码
finally:
print('卷不动了,睡觉吧')
输出结果:
很晚了,该睡觉了。
卷不动了,睡觉吧
主动触发异常:
在实际开发中,当程序不满足某条件时,通常会主动抛出异常。
语法:
raise Exception()
代码实例:
# 判断煎饼熟了没,当烹饪时间小于5时,则主动触发没熟异常;否则熟了。
# 定义一个函数,给一个形参(时间)
def demo(time):
if time < 5:
# 不满足条件,主动抛出异常
raise Exception('别着急呀,还没熟呢...')
try:
demo(4) # 调用函数,并传入实参
except Exception as e:
print("不满足条件时,主动抛出异常:", e)
else:
print('哇,已经熟了,快来吃吧..')
输出结果:
不满足条件时,主动抛出异常: 别着急呀,还没熟呢...
实例2:
def test(a, b):
if b == 0:
raise ZeroDivisionError("零不可以成为分子")
return a / b
try:
test(1, 0)
except Exception as e:
print(e)
输出结果:
零不可以成为分子
自定义异常:
当需要自定义满足一些规则时,需自定义异常;
自定义异常:通过创建一个新的异常类,自定义名字与内容,并且需要继承Exception类实现。
代码实例:
# 判断密码长度 如果密码长度小于6,则主动触发异常、并抛出异常信息(打印提示)
class shortInputError(Exception):
# 初始化
def __init__(self, lenth, min_len):
# 输入的密码长度
self.lenth = lenth
# 要求密码的最小长度
self.min_len = min_len
# 自定义输出
def __str__(self):
return f"你输入的密码长度为{self.lenth},要求不能少于{self.min_len}位,请核对。"
def demo():
try:
pwd = input("请输入密码:")
if len(pwd) < 6:
# 主动触发异常
raise shortInputError(len(pwd), 6)
except Exception as e:
print(e) # 主动触发的异常,在这里打印
else:
print('输入的密码符合要求。')
demo()
断言:
用于判断一个表达式,当表达式条件为F时触发断言异常 AssertionError;
使用python中的断言来自动检测python程序中的错误,让程序更加可靠且更易于调试:
从根本上来说,python中的断言语句是一种调试工具,用来测试某个断言条件。
如果断言条件为 True,则程序将继续正常执行;
如果断言条件为假 False,则会引发 AssertionError 异常并显示相关的错误消息。
语法:
assert 断言
代码实例:
# 以618球拍折扣为例:
def applyDiscount(racket, discount):
disPrice = int(racket['price']) * (1 - discount)
# 该语句确保在任何情况下,通过该函数计算的折后价格不低于0,也不会高于产品原价。
assert 0 <= disPrice <= racket['price']
return price
if __name__ == '__main__':
racket = {
'name': '尤尼克斯',
'price': 3200,
}
price = applyDiscount(racket, 2)
print(f'折扣后的球拍价格为{price}元')
当尝试使用反常的折扣时,比如:把商品打200%的折扣,
我们会看到,程序停止,并且触发一个 AssertionError。
这是因为不满足上述示例,applyDiscount中设置的断言条件。