14. 异常处理

一、什么是异常

程序在运行过程之中,不可避免的出现一些错误,比如:使用了没有赋值的变量、使用了不存在的索引、除 0 等等。这些错误在程序中,我们称之为异常。程序运行过程中,一旦出现异常将会导致程序立即终止,异常以后的代码全部都不会执行。

二、异常的传播

当在函数中出现异常时,如果在函数中对异常进行了处理,则异常不会继续传播。如果函数中不会对异常进行处理,,则异常会继续向函数调用处传播。如果函数调用处处理了异常,则不再传播,如果没有则继续向调用处传播。直到传递到全局作用域(主模块),如果依然没有处理,则程序终止,并显示异常信息。

当程序运行过程中出现异常以后,所有的异常信息会被保存在一个专门的异常对象,而异常传播时,实际上就是异常对象抛给了调用处。比如,ZeroDivisionError 类的对象专门用来表示除 0 的异常,NameError 类的对象专门用来处理变量错误的异常。在 Python 中提供了多个异常对象。

python 复制代码
def fun1():
    a  = 10 / 0

def fun2():
    fun1()

def fun3():
    fun2()

fun3()

三、异常处理机制

程序运行时出现异常,目的并不是让程序直接终止。Python 是希望在出现异常时,我们可以编写代码来对异常进行处理。遇到异常时,Python 中有两种处理机制。

3.1、try...except机制

在 Python 中,提供 try...catch 语句捕获并处理异常。在使用时,把可能产生异常的代码放在 try 子句中,把处理结果放在 except 子句中。这样,当 try 子句中的代码块出现异常时,就会执行 except 语句块中的内容。如果 try 语句块中代码没有异常,那么 except 语句块不会执行。这样我们就可以通过代码来处理异常,避免因为一个异常导致整个程序的终止。

我们还可以在原有的基础上在添加一个 else 子句,用于指定当 try 语句块中没有出现异常时要执行的语句块。该语句块中的内容当 try 语句中发现异常时,将不被执行。

我们还可以在添加一个 finallty 子句。该子句中的代码无论是否发生异常都会被执行。

python 复制代码
try:
    代码块(可能出现异常的代码)
except [异常名 [as 异常对象名]]:
    代码块(出现错误以后的处理方式)
[else:
    代码块(没出现时要执行的语句)]
[finally:
    代码块(无论是否出现异常,该子句都会执行)]

如果 except 后面不跟任何内容,则此时它会捕获所有的异常。

python 复制代码
print("异常处理之前")

try:
    # try中放置的是可能错误的代码
    print(10/0)
# 如果except后不跟任何内容,此时它会获取所有的错误
except:
    # except中放置的是出现以后的处理代码
    print("出现异常")
# 这是一个可选的结构,表示没有出现异常要执行的代码
else:
    print("程序正常异常,没有错误")
# 这是一个可选结构,表示无论是否出现异常,最后都要执行的语句
finally:
    print("无论是否出现异常,该子句都会执行")

print("异常处理之后")

如果 except 后面跟者异常类型,那么该类型对应的异常。我们还可以在在异常类后面跟着一个 as xxx,此时 xxx 就是异常对象。

python 复制代码
try:
    # try中放置的是可能错误的代码
    print(10/0)
    print(a)
    1 + "hello"
# 如果except后不跟着异常的类型,那么它只会捕获该类型对应的异常
# 可以在异常类后面跟着一个 as xxx,此时xxx就是异常对象
except NameError as e:
    # except中放置的是出现以后的处理代码
    print("出现NameError")
    print(e)
except ZeroDivisionError as e:
    # except中放置的是出现以后的处理代码
    print("出现ZeroDivisionError")
    print(e)
# Exception 是所有异常类的父类
# 如果except后跟的是 Exception,它会捕获所有的异常
except Exception as e:
    print("未知异常")
    print(e)

在使用 try...except语句捕获异常时,如果在 except 后面不指定异常名称,则表示捕获全部异常;

在使用 try...except语句捕获异常时,当程序出现异常并处理完后,程序继续执行;

我们可以在 except 语句后面使用一对小括号将可能出现的异常名称括起来,多个异常之间使用逗号分隔。

3.2、raise机制

如果某个函数或方法可能会产生异常,但不想在当前函数或方法中处理这个异常,则可以使用 raise 语句在函数或方法中抛出异常。

python 复制代码
raise [异常类型名[异常描述]]

如果异常类型名为可选参数,它用于指定抛出的异常名称以及异常信息的相关描述。如果省略,就会把当前的错误原样抛出。异常描述也可以省略,如果省略,则在抛出异常时,不附带任何描述信息。

python 复制代码
def div(a,b):
    if b == 0:
        # raise用于向外部抛出异常
        # 后面可以根一个异常类,或异常类的对象
        raise ZeroDivisionError("除0异常")
    return a/b

print(div(10,0))

四、自定义异常类

我们也可以自定义异常类,只需要创建一个类继承 Exception 类即可。

python 复制代码
class MyException(Exception):
    pass
相关推荐
沐霜枫叶2 小时前
解决pycharm无法识别miniconda
ide·python·pycharm
途途途途2 小时前
精选9个自动化任务的Python脚本精选
数据库·python·自动化
蓝染然2 小时前
jax踩坑指南——人类早期驯服jax实录
python
许野平2 小时前
Rust: enum 和 i32 的区别和互换
python·算法·rust·enum·i32
问道飞鱼2 小时前
【Python知识】Python进阶-什么是装饰器?
开发语言·python·装饰器
AI视觉网奇3 小时前
Detected at node ‘truediv‘ defined at (most recent call last): Node: ‘truediv‘
人工智能·python·tensorflow
GuYue.bing3 小时前
网络下载ts流媒体
开发语言·python
牛顿喜欢吃苹果4 小时前
linux创建虚拟串口
python
-Mr_X-4 小时前
FFmpeg在python里推流被处理过的视频流
python·ffmpeg
一个不秃头的 程序员4 小时前
代码加入SFTP JAVA ---(小白篇3)
java·python·github