异常

很久没写博客了

什么是异常

异常就是程序运行时发生错误的信号(在程序出现错误时,则会产生一个异常,若程序没有处理它,则会抛出该异常,程序的巡行也随之终止).

  • 异常的组成
    • 1.追踪信息(具体发生异常的位置 以及函数的调用顺序)
    • 2.异常的类型(错误的类型)
    • 3.异常的消息(详细的错误信息)

异常_第1张图片

  • 异常的分类
    • 1.语法异常:就是语法检查时就会报错的异常,这种异常很low,不应该犯
      比较好避免
      如果用编译器 会自动提示
      如果你牛逼到用本文编辑器写,应该不会出现这种错误.
    • 2.逻辑异常(运行时异常)
      这种异常只有在代码被执行时才能发现
      我们处理的重点就是逻辑异常
      特点:
      • 在没有运行代码前,无法发现
      • 如果运行时异常已经发生并且没有正确处理他 就抛出错误信息 并中断程序的执行 这是要我们学校异常解决的问题

我们学习异常处理就是为了让我们的程序更加稳定(健壮性) 不容易崩溃

常见异常

常见错误 发生原因
NameError 找不到变量或函数名
ValueError 在调用函数是给的值不正确
TypeError 类型错误 调用一个不能调用的类型
ZeroDivisionError 除数不能为0
KeyError 没有Key
IndexError 索引不存在
StopIteration 没有更多的值可以迭代
FileNotFoundError 文件不存在
io.UnsupportedOperation 文件的操作不支持
AttributeError 没有这个属性
KeyboardInterrupt 程序被强行终止/ctrl+c

异常处理

处理异常常用语法

try:
	'可能出现异常的代码'
except 异常类型:
	'当异常发生并且异常类型匹配执行except中的代码'

注意:一旦try中有代码抛出异常,后面的代码全都不执行

  • 尝试一下捕捉异常
print("staring.....")
try:
    name
except NameError:
    print("名字找不到!")
print("end.......")

异常_第2张图片

  • 多种异常类型处理,当代码可能出现多种异常时
print("staring.....")
try:
    # name
    [][-1]
    pass
except NameError:
    print("名字找不到!")
except IndexError:
    print("索引超出范围")
print("end.......")

异常_第3张图片

  • 多种异常写法二:
    没法判断具体是哪个错误发生
print("staring.....")
try:
    {}["aaa"]
    # name
    # [][-1]
    1/0
except (NameError,IndexError,ZeroDivisionError):
    print("可能名字找不到! 可能所以超出范围 可能除数为0")
print("end.......")
  • 万能异常类型:因为异常类型太多
    Exception 或 BaseException 基于OOP的继承和多态
print("staring.....")
try:
    # {}["aaa"]
    # name
    # [][-1]
    1/0
except Exception:
    print("可能名字找不到! 可能所以超出范围 可能除数为0")
print("end.......")

处理异常不太常用的语法

  • 语法一:else
try:
	'可能出现异常的代码'
except 异常类型:
	'捕捉到异常执行的代码'
else:
	'没有发生异常时执行的代码'

如果在try中没有出现异常

print("start...")
try:
    # 1/0
    #[][1]
    pass
except ZeroDivisionError:
    print("除数异常")
except NameError:
    print("名字异常")
else:
    print("else会在 try中没有异常时执行")
print("end...")

异常_第4张图片
你可以尝试,让try里代码出现异常,else中的代码就不会被执行

  • 语法二:finally(通常用来回收系统资源)
try:
	'可能出现异常的代码'
except 异常类型:
	'捕捉到异常执行的代码'
finally:
	'无论是否发生异常,都会在发生异常后执行finally'
print("start...")
try:
    # 1/0
    [][1]
    pass
except ZeroDivisionError:
    print("除数异常")
except IndexError:
    print("索引异常")
else:
    print("else会在 try中没有异常时执行")
finally:
    print("finally 无论异常是否发生 都会执行!")
print("end...")

异常_第5张图片
可以自己尝试,没有捕捉异常时和没有发生异常时的结果

使用finally来回收资源

try:
    f = open(r"D:\上海python全栈4期\day31\异常处理\1今日内容","rt",encoding="utf-8")
    f.read()
    f.write("123")
except Exception:
    print("发生异常了")
finally:
    print("关闭文件!")
    f.close()

主动抛出异常raise

当程序中有一些限制,然而用户没有遵守时,我们就可以主动抛出异常

  • 语法
raise 异常类型('异常的详细信息')
# 类型必须是BaseException的子类

例子:

age = input("请输入整型的年龄:")
if not age.isdigit():
    raise TypeError("你输入的不是整型!")
age = int(age)
print("十年后你%s岁" % (age + 10))

异常_第6张图片

断言assert

断言:可以理解为断定,就是很明确

  • 什么时候需要断定?
    当下面的代码必须依赖上面代码的正确数据是
  • 语法
assert 结果给Bool值的表达式
pass
'''
当值为True 则继续执行下面的代码
当值为False 抛出异常 AssertionError 表示断言失败
没有assert 也可以使用if  assert仅仅是简化了代码
'''

例子:

li = []
#if len(li) < 1:
#    raise ValueError("列表中没有数据!")	
assert len(li) > 0
pass
'''
if判断raise抛出异常 和 assert断言都可以用
'''
# 自己运行尝试结果

自定义异常

当系统提供的这些异常类型和你要描述的错误不匹配时,就需要自定义异常类型

  • 语法:
class 自定义异常类型名称(BaseException):
	pass

自定义异常类型是为了更具体描述你的错误,让使用者一眼就看出来

  1. 如何自定义异常类型
  2. 在except中,使用as来获取异常对象
# 自定义异常类
class UnlikeError(BaseException):
    def __init__(self,msg):
        self.msg = msg
# 函数中可能抛出异常
def hello():
    text = input("输入一段话:")
    if text == "你真帅":
        print("你说得对!")
    else:
        raise UnlikeError("你再看看...")
# 捕获异常
try:
    hello()
# 获取异常对象
except UnlikeError as e:
    print(e.text)

什么时候用异常处理

try…except是你附加给你的程序的一种异常处理的逻辑
不应该滥用try except
如果你知道为什么出错,就应该吧代码修改正确
加上try…except会导致你的代码可读性变差
我的老师说:异常处理不是你错误逻辑的擦屁股纸,只有在错误发生的条件无法预知的情况下,才应该加上try…except

你可能感兴趣的:(Python)