python

关注公众号 jb51net

关闭
首页 > 脚本专栏 > python > Python异常处理

Python学习之异常处理详解

作者:渴望力量的哈士奇

正常情况下,我们的程序是自上而下的逐行执行,执行到最后一行才会终止程序的执行。而异常的情况会导致我们的程序半途而废停止了执行。本文将通过示例详细讲解Python中的异常处理,感兴趣的可以学习一下

本章节主要学习 python 中的异常处理,来看一下该章节的内容有哪些。首先我们需要了解 什么是异常与异常的处理 ,然后再继续 异常的语法结构

什么是异常与异常处理

异常 —> 可以理解为不同寻常。

正常情况下,我们的程序是自上而下的逐行执行,执行到最后一行才会终止程序的执行。而异常的情况会导致我们的程序半途而废停止了执行。一般情况下的停止执行都是因为我们的程序出错而造成的,而异常就是错误,异常的出现会导致我们的程序崩溃并停止运行。这在我们的工作中是非常不友好的!

纵观程序的一生,都不能保证说程序一定不会出错。所以当遇到错误的时候,为了不影响程序的执行,我们就需要对这些异常进行处理, Python 中的异常机制,可以监控并捕获到异常。当程序出现错误的时候对异常进行临时妥善的处理,就可以使得程序继续正常的运行。

总结:

异常的本质就是错误

异常的出现会导致程序的崩溃且会停止执行

监控异常并捕获,将造成异常的程序进行妥善的处理可以使得程序能够继续正常的运行

接下来我们就快快的看一下 究竟如何捕获异常并进行异常处理的语法吧。

异常的语法

try:                   # 异常的关键字,尝试的意思
    <代码块1>               # 被 try 关键字检查并保护的业务代码块
    
except <异常的类型>:         # 发现异常后的处理关键字,会跟随一个错误类型(异常类型),异常类型可以不填写
    <代码块2>               # try 的代码块出现错误之后,就会执行 except 的代码块
                       # 这里一般都是当 try 代码块出现错误之后的补救逻辑

来看一个简单的示例:

1 / 0		# 我们都知道 0 不能被整除,所以产生了下面这样的报错

# >>> 执行结果如下
# >>> ZeroDivisionError: division by zero 

# >>> 我们管代码的报错叫做 异常的抛出 ,这个报错信息告诉了我们为什么报错,同时业务也会被停止。
# >>> 在程序中,我们是允许出错的,但是需要对可能遇见的异常捕获,
# >>> 进行合理的处理,让程序遇到异常可以合理的运行

看一下针对上文示例的异常进行的捕获

try:
    1 / 0
except:
    print('注意:0 不可以被 1 整除')
    print('ZeroDivisionError: division by zero 已捕获,程序继续执行')

# >>> 执行结果如下
# >>> 注意:0 不可以被 1 整除
# >>> ZeroDivisionError: division by zero 已捕获,程序继续执行

# >>> 虽然 try 代码块抛出了异常,但是我们通过 except 进行了合理的规避,使得我们的程序继续向下执行

接下来我们再利用我们之前学到的知识点 upper() 函数做一个小案例:

定义一个 upper ,利用 upper() 函数 。将传入的字符串转为大写,如传入参数非 字符串 ,捕获该异常并处理。

def upper(str_data):
    new_str = None

    try:
        new_str = str_data.upper()
    except:
        print('upper() 函数转换字符大写失败!', '返回结果为:', new_str)
    return new_str


result = upper('test')
print('传入参数返回值为:', result)

# >>> 执行结果如下:
# >>> 传入参数返回值为: TEST


result = upper(1)
print(result)

# >>> 执行结果如下:
# >>> upper() 函数转换字符大写失败! 返回结果为: None

捕获通用异常

刚刚我们通过 try…except… 捕获了异常并进行了合理的处理,但是我们并不知道错误的原因是什么。所以我们必须获取 异常的类型 ,首先我们来学习一下如何获取通用异常类型, 通用异常类型 是我们无法确定是那种异常的情况下使用的一种捕获方法。

用法如下:

try:
    <代码块>
except Exception as e:        # 把通用异常的错误原因转换成变量 e , as 为关键字
                            # 也可以理解为 将 Exception 通用异常类型 起一个别名 e
                            # e 变量名可以起任意名字,一般约定成俗都会使用 e 作为异常捕获的变量名
                            # e 就是 error 的缩写
    <异常代码块>

通用异常捕获示例如下:

def upper(str_data):
    new_str = None

    try:
        new_str = str_data.upper()
    except Exception as e:
        print('upper() 函数转换字符大写失败!', '返回结果为:{}'.format(e))
    return new_str


result = upper(1)
print(result)


# >>> 执行结果如下:
# >>> upper() 函数转换字符大写失败! 返回结果为:'int' object has no attribute 'upper'

捕获具体异常

捕获具体的异常就是我们可以确定在 try 的代码块中会出现哪种具体的异常类型,并将其捕获的方法。语法方面与通用异常一样,在异常类型区域书写 具体的异常类型 就可以了。

我们以上文的 ZeroDivisionError: division by zero 为例

try:
    1 / 0
except ZeroDivisionError as e:		# 书写指定的异常类型:ZeroDivisionError
    								# ZeroDivisionError 是Python内置的具体异常:0不能被整除
    print(e)

# >>> 执行结果如下:
# >>> division by zero

小节:思考一个问题,工作中我们是使用 通用的异常 还是 具体的异常 呢?

从方便的角度来说,使用通用的异常会比较简单。开发成本低,不需要关心具体的异常类型是什么。其实 Exception 也不知知道具体的异常是哪一种类型,它需要去浩瀚的异常库查找,找到之后进行对应的抛出,虽然没有 具体指定异常 处理的那么快,但是这个处理速度也是无感知的。

如果我们能知道 try 代码块中 可能出现的具体异常类型,还是希望使用具体的异常类型。这样可以精准的对应错误;

==需要注意的是:当我们的 try 代码块中,没有出现我们指定的 具体异常 类型,代码执行依然是会报错的。==所以各有利弊,可以根据我们工作中业务的具体情况进行使用。

如何捕获多个异常

在我们平时的开发工作中,很可能在同一个代码块中出现多个异常类型。那么我们该如何支持多个异常的捕获呢?

其实异常的捕获是非常灵活的,也支持多个异常捕获的方式。

捕获多个异常 - 方法1

try:
    result = 1 / 0
except ZeroDivisionError as e1:
    print(e1)
except Exception as e2:            # 可以使用多个 except 来捕获多个异常
    print('this is a public except , bug is %s' % e2)
    
# >>> 需要注意的是,当 except 代码块中有多个异常的时候,当捕获到第一个异常后,不会在继续往下捕获。

需要注意的是,当 except 代码块中有多个异常的时候,当捕获到第一个异常后,不会在继续往下捕获。

捕获多个异常 - 方法2

try:
    result = 1 / 0
except (ZeroDivisionError, Exception) as e:        # 在 except 后面的小括号内定义多个 异常类型 ,(小括号其实是元组)
                                                # 当 except 后面使用元组包裹多个 异常类型 时,捕获到哪种异常类型就抛出哪种
    print(e)

示例如下:

def test():

    try:
        print(name)     # 因为不存在 name 这个变量,所以会抛出一个 NameError: name 'name' is not defined 异常
                        # 尝试捕获  NameError 异常
    except (ZeroDivisionError, NameError) as e:
        print(e)
        print(type(e))


test()

# >>> 执行结果如下:
# >>> name 'name' is not defined
# >>> <class 'NameError'>

比较常用的捕获异常方法是第二种。

到此这篇关于Python学习之异常处理详解的文章就介绍到这了,更多相关Python异常处理内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文