异常

异常介绍

当Python无法正常处理程序时就会发生一个异常,会影响程序的正常执行。异常也是Python对象,表示一个错误。

ab = int(input('请输入整数:'))   # 当输入的内容为小数的时候会报错

cd = float(input('请输入整数:'))  # 当不小心输入两个小数点的时候也会报错

print('1'*20)
ef = int(input('请输入整数:'))   # 当输入小数时,会终止程序运行,下面的语句不会执行
print('1'*20)

异常捕获

当Python脚本有发生异常的可能时,就需要捕获异常,避免程序终止执行。

try:
    正常程序执行此块代码
except:
    抛出错误执行此代码块

练习:用键盘输入浮点数并进行输出,如果出现异常,就返回为1

try:
    # 正常程序时执行代码块
    ipt = float(input('请输入一个小数:'))
    print(ipt)

except:
    # 异常程序时执行代码块
    print(1)

上述代码可以在程序出错时不让代码终止,但是不能输出异常的信息。

异常类型捕获

记录下具体异常种类,可以捕获具体的异常信息。

try:
    pass
except 当前异常对象 as e:  # 把当前异常对象赋值给e
    print(e)

当前异常对象可以为:IndexError、ZeroDivisionError、ValueError、NameError

li = [1,2,3]
print(li[4])  # IndexError
print(2/0)      # ZeroDivisionError
print(int('a'))   # ValueError
prin()      # NameError

比如出现索引错误。

try:
    li = [1,2,3]
    print(li[2])    # 程序没有问题时,正常运行,不执行except的代码
    print(li[4])    # 程序运行错误时,才会执行except内部的代码
except IndexError as e:
    print(e)	# list index out of range

此时程序并未出现报错,而是输出了错误的类型。如果出现错误的类型不是IndexError,同样会出现终止程序运行。

try:
    li = [1,2,3]
    print(li[2])
    print(int('a'))
except IndexError as e:
    print(e)	# 会报错:ValueError

可以通过help( __builtin __)查看所有的异常类型。

python中小数点错误 python输入小数报错_python

从上图中可以看到,所有的异常类型都继承了Exception类,Exception类可以捕获到它含有的所有子类(异常)。

try:
    li = [1,2,3]
    # print(li[3])    # list index out of range
    print(int('a'))   # invalid literal for int() with base 10: 'a'
except Exception as e:
    print(e)

细分错误,非常有必要,一般用于载入日志,查看错误信息。在细分的异常种类下,最后才放入Exception,避免没有考虑到细小的错误信息。

try:
    li = [1,2,3]
    print(li[3])    # list index out of range
    print(int('a'))   # invalid literal for int() with base 10: 'a'
except IndexError as e:
    print(e)        # 载入日志
except ValueError as e:
    print(e)        # 载入日志
except Exception as e:
    print(e)

try-except-else

如果抛出异常,执行except内部代码;如果程序正常,执行else内部代码。

程序正常运行时
try:
    li = [1,2,3]
    print(li[2])
except IndexError as e:
    print(e)
except Exception as e:
    print(e)
else:
    print('程序正常时,执行的代码')	
# 3 
# 程序正常时,执行的代码
程序有异常时
try:
    li = [1,2,3]
    print(li[3])
except IndexError as e:
    print(e)
except Exception as e:
    print(e)
else:
    print('程序正常时,执行的代码')	
# list index out of range

try-finally

不管程序有无发生异常,都将执行finally内部代码。

try:
    li = [1,2,3]
    print(li[3])
except IndexError as e:
    print(e)
except Exception as e:
    print(e)
else:
    print('程序正常时,执行的代码')
finally:
    print('不管程序怎样,都会执行')
# list index out of range
# 不管程序怎样,都会执行
try:
    li = [1,2,3]
    print(li[2])
except IndexError as e:
    print(e)
except Exception as e:
    print(e)
else:
    print('程序正常时,执行的代码')
finally:
    print('不管程序怎样,都会执行')
# 3
# 程序正常时,执行的代码
# 不管程序怎样,都会执行

else和finally只能有一个。

主动触发异常

在实际开发中,在程序不满足某条件时,通常会主动抛出异常。

raise Exception(要抛出的异常信息)

练习 : 判断煎饼熟了没,当烹饪时间小于5时,则主动触发没熟异常;否则熟了

def CookJianbing(level):
    if level < 5:
        raise Exception('还没有熟')
try:
    CookJianbing(6)
except Exception as e:
    print(e)
else:
    print('已经熟了')

记录日志的时候,把错误记录到相应的模块内。
例题:如果函数db() 有错误,主动抛出异常(raise),如果是调用函数自身的错误,就把错误载入日志中。

def db():
    # 告诉使用者,此处有错误
    raise Exception('数据库的错误')
def test1():
    try:
        db()
    except Exception as e:
        print('db函数错误:', e)
    try:
        li = [1,2,3]
        print(li[3])
    except Exception as e:
        print('函数自身错误:', e)

test1()
# db函数错误: 数据库的错误
# 函数自身错误: list index out of range

自定义异常

当需要自定义满足一些规则时,就可以自定义异常。
自定义异常通过创建一个新的异常类,自定义名字与内容,并且需要继承Exception类实现,类的名字和内容的限定是由自己去编写的。

class NameError(Exception):
    def __init__(self,msg):
        self.info = msg

    def __str__(self):
        return self.info    # 名字错误

# e = NameError('名字错误')
# print(e)

try:
    # 用raise去主动触发异常
    raise NameError('名字错误')  # e = NameError('名字错误')
except NameError as e:
    print(e)

断言

assert断言用于判断一个表达式,当表达式条件为False时触发断言异常AssertionError,不满足条件就直接抛出异常。

assert 断言(条件)

条件成立时,往下执行代码;条件不成立时,直接抛出异常AssertionError。

print('1'*20)
assert '1' == 1
print('1'*20)

注意,断言用于强制用户服从,可捕获,但是一般不捕获。