前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Python异常

Python异常

原创
作者头像
Heaven645
发布2024-07-26 23:21:54
501
发布2024-07-26 23:21:54
举报
文章被收录于专栏:Python学习

前言

在Python中,异常是一种特定的对象,能够在程序运行过程中被抛出和处理。有效地管理异常不仅可以增强程序的稳定性,还可以提高用户体验,使程序能够优雅地处理错误情况。本章详细讲解了异常的基本概念、如何捕获和处理异常以及异常的传递性。


本篇文章参考:黑马程序员

一、什么是异常

当检测到一个错误时,Python解释器无法继续执行程序,反而会抛出错误提示,这就是我们所称的“异常”,也就是常说的“bug”。

bug这个单词是怎么诞生的呢?

"bug"这个词最初的确是指“虫子”。在英语中,"bug"可以用来描述各种小昆虫。早期计算机采用大量继电器工作,马克二型计算机出现了故障,技术人员尝试了多种方法,最后定位到第70号继电器出错。负责人哈珀仔细观察这个出错的继电器,发现一只飞蛾躺在中间,已经被继电器打死。她小心翼翼地用镊子将这只蛾子取出,将其用透明胶带粘贴在“事件记录本”上,并注明为“第一个发现虫子的实例”。自此之后,导致软件故障的缺陷便被称为“bug”。

代码语言:python
代码运行次数:0
复制
# 打开一个不存在的文件
f=open("D:/test.txt","r",encoding="UTF-8")

运行结果:

控制台打印出的错误信息通常表示在程序运行过程中遇到的异常(Exception)。当程序遇到无法处理的错误时,就会抛出异常,并在控制台输出相关的错误信息,包括异常类型、错误描述以及错误发生的位置。

二、捕获异常

为什么要捕获异常呢?

世界上没有完美的程序,任何程序在运行的过程中,都有可能出现异常,也就是出现bug,导致程序无法完美运行下去。

我们要做的,不是力求程序完美运行。而是在力所能及的范围内,对可能出现的bug,进行提前准备、提前处理。这种行为我们称之为异常处理(即捕获异常)。

当我们的程序遇到了Bug, 有以下两种情况:

  1. 整个程序因一个Bug停止运行。
  2. 程序能够提醒用户Bug的发生,并继续正常运行。

在实际工作中,我们肯定不能因为一个小小的Bug就让整个程序全部奔溃,所以我们希望的是达到第二种情况。为此,我们需要使用异常捕获技术。

捕获异常的作用:提前预测某个地方可能会出现异常,并做好相应的准备。当实际发生异常时,我们可以采取后续措施来处理这些异常。

①捕获常规异常

基本语法:

try:

  可能引发异常的代码

except:

  如果出现异常执行的代码

代码语言:python
代码运行次数:0
复制
# 捕获异常
try:
    # 打开一个不存在的文件
    f=open("D:/test.txt","r",encoding="UTF-8")
except:
    print("出现异常了,因为文件不存在,改为w模式打开")
    # w模式:当文件不存在时会创建一个文件
    f=open("D:/test.txt","w",encoding="UTF-8")

输出结果:

出现异常了,因为文件不存在,改为w模式打开

②捕获指定异常

基本语法:

try:

  可能引发异常的代码

except SpecificException as e:

  处理特定异常的代码

代码语言:python
代码运行次数:0
复制
# 捕获指定异常
try:
    print(name)
# 捕获 NameError 异常,并将异常对象赋值给变量 'e' 
except NameError as e:
    # 输出提示信息 
    print("出现变量未定义异常")
    # 输出异常对象 'e' 的信息
    print(e)

输出结果:

出现变量未定义异常

name 'name' is not defined

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

代码语言:python
代码运行次数:0
复制
# 捕获指定异常
try:
    1/0
except NameError as e:
    print("出现变量未定义异常")
    print(e)

运行结果:

③捕获多个异常

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

代码语言:python
代码运行次数:0
复制
# 捕获多个异常
try:
    1/0
except (NameError,ZeroDivisionError) as e:
    print("出现变量未定义或者除以0的异常")
    print(e)

输出结果:

出现变量未定义或者除以0的异常

division by zero

代码语言:python
代码运行次数:0
复制
# 捕获多个异常
try:
    print(name)
except (NameError,ZeroDivisionError) as e:
    print("出现变量未定义或者除以0的异常")
    print(e)

输出结果:

出现变量未定义或者除以0的异常

name 'name' is not defined

代码语言:python
代码运行次数:0
复制
# 捕获多个异常
try:
    print(name)
    1/0
except (NameError,ZeroDivisionError) as e:
    print("出现变量未定义或者除以0的异常")
    print(e)

输出结果:

出现变量未定义或者除以0的异常

name 'name' is not defined

仔细观察这个输出结果,为什么会输出name 'name' is not defined但是不会输出division by zero呢?

这是因为在Python中捕获多个异常时,try 块中的代码是自上而下执行的,一旦遇到异常,程序会立刻跳转到相应的 except 块,后续的代码将不再执行。

这段代码中,print(name) 这行会首先执行,然而 name 变量并不存在,所以会首先引发NameError异常并立即跳转到对应的 except 块来处理这个异常,而不会继续执行 try 块中的后续代码。因此,1/0 这行代码并不会执行,所以不会引发 ZeroDivisionError异常。

④捕获所有异常

基本语法1:

try:

  可能引发异常的代码

except:

  如果出现异常执行的代码

基本语法2:

try:

  可能引发异常的代码

except Exception as e:

  如果出现异常执行的代码

代码语言:python
代码运行次数:0
复制
# 捕获所有异常
# 写法一:(这种写法较为常用)
try:
    print(name)
except Exception as e:
    print("出现异常了")

# 写法二:
try:
    1/0
except:
    print("出现异常了")

输出结果:

出现异常了

出现异常了

⑤异常else

else表示的是如果没有异常要执行的代码。

代码语言:python
代码运行次数:0
复制
try:
    print("Hello")
except Exception as e:
    print("出现异常了")
else:
    print("没有出现异常")

输出结果:

Hello

没有出现异常

⑥异常finally

finally表示的是无论是否异常都要执行的代码。

代码语言:python
代码运行次数:0
复制
try:
    print("Hello")
except Exception as e:
    print("出现异常了")
else:
    print("没有出现异常")
finally:
    print("我是finally,有没有异常我都会执行")

输出结果:

Hello

没有出现异常

我是finally,有没有异常我都会执行

代码语言:python
代码运行次数:0
复制
try:
    1/0
except Exception as e:
    print("出现异常了")
else:
    print("没有出现异常")
finally:
    print("我是finally,有没有异常我都会执行")

输出结果:

出现异常了

我是finally,有没有异常我都会执行

三、异常的传递

异常是具有传递性的。

代码语言:python
代码运行次数:0
复制
# 定义一个出现异常的方法
def func1():
    print("func1 开始执行")
    num = 1 / 0     # 除以0的异常
    print("func1 结束执行")

# 定义一个无异常的方法,调用上面的方法
def func2():
    print("func2 开始执行")
    func1()
    print("func2 结束执行")

# 定义一个方法,调用上面的方法
def main():
    try:
        func2()
    except Exception as e:
        print(f"出现异常了,异常的信息是:{e}")

main()

输出结果:

func2 开始执行

func1 开始执行

出现异常了,异常的信息是:>division by zero

【分析】

当函数func01中发生异常, 并且没有捕获处理这个异常的时候, 异常会传递到函数func02,;当func02也没有捕获处理这个异常的时候,异常会传递到main函数;最终,main函数捕获了这个异常, 这就是异常的传递性。

注意:如果函数都没有捕获异常, 程序就会报错。

代码语言:python
代码运行次数:0
复制
# 定义一个出现异常的方法
def func1():
    print("func1 开始执行")
    num = 1 / 0     # 除以0的异常
    print("func1 结束执行")

# 定义一个无异常的方法,调用上面的方法
def func2():
    print("func2 开始执行")
    func1()
    print("func2 结束执行")

# 定义一个方法,调用上面的方法
def main():
    func2()
main()

运行结果:

利用异常具有传递性的特点,在main函数中设置异常捕获便可保证程序不会因为异常崩溃。因为整个程序无论在哪里发生异常,异常最终都会传递到main函数中,进而确保所有的异常都会被捕获。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 一、什么是异常
  • 二、捕获异常
  • 三、异常的传递
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档