异常—python

一、异常

当检测到一个错误时,Python解释器就无法继续执行了,反而出现了一些错误的提示,这就是异常, 也就是我们常说的BUG,那BUG是怎么由来的呢?

例如:

print(1/0)

我们在小学的时候就知道0不能作除数,运行这条代码,程序不仅无法执行还会报错,零除法错误就是一种异常。

二、异常处理

异常实际上就是一种错误,我们写程序出错误是一件很正常的事情,关键在于发现错误、解决错误。我们要做的,不是要求程序完美, 而是在力所能及的范围内,对可能出现的bug,进行提前准备、提前处理,这种行为叫做异常处理(捕获异常)。

在之前的学习中, 我们所有的程序遇到BUG就会出现整个程序因为一个BUG停止运行的情况, 也就是整个程序直接奔溃。但是在实际工作中, 我们不能因为一个小的BUG就让整个程序全部奔溃, 我们希望的是:对BUG进行提醒后整个程序继续运行。那我们就需要捕获异常:提前假设某处会出现异常,做好提前准备,当真的出现异常的时候,可以有相应的解决方案。

2.1捕获常规异常

语法:

try:    

     可能发生错误的代码

except:    

     如果出现异常执行的代码

我们在文件一节学习了open函数——http://t.csdnimg.cn/jVDYK

  • 用open函数以只读模式‘r’打开一个文件,如果文件不存在,运行后会报错。
  • 用open函数以写入模式‘w’打开一个文件,如果文件不存在,创建新文件进行写入。

假设我们不知道文件test.txt是否存在,我们把以只读模式打开test.txt作为可能发生错误的代码,把以写入模式打开test.txt作为如果出现异常执行的代码。

try:
    f = open('test.txt', 'r', encoding='UTF-8')
    print("文件test.txt存在")
except:
    f = open('test.txt', 'w', encoding='UTF-8')
    print("文件test.txt不存在,创建")

输出:

文件test.txt不存在,创建

2.2捕获指定异常

语法:

try:    

     可能发生错误的代码

except 错误种类 as e:    

     如果出现异常执行的代码

如果我们打印输出一个未定义的变量

print(ret)

运行起来会报错:

我们捕捉这种特定的异常NameError,代码如下:

try:
    print(ret)
except NameError as e:
    print("变量名称未定义错误")

输出:

变量名称未定义错误

我们再看另一个代码示例,捕捉这种特定的异常FileNotFoundError:

try:
    f = open('test.txt', 'r', encoding='UTF-8')
except FileNotFoundError as e:
    print("文件不存在错误")

输出:

文件不存在错误

如果尝试执行的代码的异常类型和要捕获的异常类型不一致,则无法捕获异常。

try:
    f = open('test.txt', 'r', encoding='UTF-8')
except NameError as e:
    print("文件不存在错误")

出现的代码异常是文件不存在错误,捕获的异常类型是变量名称未定义错误,两者不一致,无法捕捉,运行会报错。

2.3捕获多个异常

当捕获多个异常时,可以把要捕获的异常类型的名字,放到except 后,以元组的方式进行书写。

代码示例:

try:
    print(1/0)
except (NameError,FileNotFoundError,ZeroDivisionError) as e:
    print('变量名称未定义错误/文件不存在错误/零除法错误')

输出:

变量名称未定义错误/文件不存在错误/零除法错误

代码示例:

try:
    f = open('test.txt', 'r', encoding='UTF-8')
except (NameError,FileNotFoundError,ZeroDivisionError) as e:
    print('变量名称未定义错误/文件不存在错误/零除法错误')

输出:

变量名称未定义错误/文件不存在错误/零除法错误

代码示例:

try:
    print(ret)
except (NameError,FileNotFoundError,ZeroDivisionError) as e:
    print('变量名称未定义错误/文件不存在错误/零除法错误')

输出:

变量名称未定义错误/文件不存在错误/零除法错误

如何在捕获异常的同时准确地输出描述信息呢?

输出变量e即可,代码示例:

try:
    print(ret)
except (NameError,FileNotFoundError,ZeroDivisionError) as e:
    print(e)

输出:

name 'ret' is not defined

2.4捕获所有异常

捕获所有异常有两种方式,第一种就是捕获常规异常的方式,第二种如下所示:

语法:

try:    

     可能发生错误的代码

except Exception as e:  

     如果出现异常执行的代码

方式一:

try:
    print(ret)
except:
    print('errno')

输出:

errno

方式二:

try:
    print(ret)
except Exception as e:
    print(e)

输出:

name 'ret' is not defined

三、异常处理中的else与finally

3.1异常处理中的else

语法:

try:    

     可能发生错误的代码

except:  

     如果出现异常执行的代码

else:

     如果没有异常要执行的代码

代码示例:

try:
    print(5/1)
except:
    print('errno')
else:
    print('perfect')

输出:

5.0
perfect

3.2异常处理中的finally

语法:

try:    

     可能发生错误的代码

except:  

     如果出现异常执行的代码

finally:

     无论是否异常都要执行的代码

代码示例:

try:
    print(5/0)
except:
    print('errno')
finally:
    print('阳光总在风雨后')

输出:

errno
阳光总在风雨后

代码示例:

try:
    print(5/1)
except:
    print('errno')
else:
    print('perfect')
finally:
    print('阳光总在风雨后')

输出:

5.0
perfect
阳光总在风雨后

注意:异常处理中的else与finally都是可选的,可以写也可以不写。

四、异常的传递性

请先看这个函数多层调用的例子:

def func1():
    ret=1/0
    print(ret)

def func2():
    print('func2的开始')
    func1()
    print('func2的结束')

def main():
    func2()

main()

运行后报错:

使用异常处理后:

def func1():
    ret=1/0
    print(ret)

def func2():
    print('func2的开始')
    func1()
    print('func2的结束')

def main():
    try:
        func2()
    except Exception as e:
        print(e)

main()

输出:

func2的开始
division by zero

请看程序执行的顺序:

我们通过输出结果,可以了解到:

这说明异常不是必须在真正出现异常的地方被捕获,可以在高的层级被捕获,因为异常是可以传递的。

利用异常具有传递性的特点, 当我们想要保证程序不会因为异常崩溃的时候, 就可以在main函数中设置异常捕获, 由于无论在整个程序哪里发生异常, 最终都会传递到main函数中, 这样就可以确保所有的异常都会被捕获。

  • 13
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值