一步一步展示并总结Python的异常

简介: 正式的Python专栏第17篇,同学站住,别错过这个从0开始的文章!

写程序,写多了,就容易出bug,当然也容易出现Exception异常!


什么是错误与异常Exception?

这个跟语法错误不一样,语法错误编译器会直接提示处理(在程序运行之前)。 比如IndentationError,这种是语法级别的异常,它也是Exception的子类)


出bug,则是在运行过程中产生超乎意料的处理结果,逻辑处理错误,但是这类错误通常不会让程序中断,往往是反应在最后的结果输出中,发现偶然几次运行跟预期的不一样,或者偶然几个输入的输出结果不符合总体运行规律。


异常就是程序中间出现 值/操作 不在系统内设定预期值内,在程序执行过程中产生的错误(不合法的数据类型,超预期设定的像磁盘/网络/文件故障等等),而且错误会被程序抛出,中止后续运行。 所以有时候我们也称呼异常为:运行时错误!


可能小白不太懂,比如下面一个现象,有点高能:


小白打算申请跟Python编译器登记结婚? 无法理解的,称之为错误!

小白跟一个萌妹子结婚,这是正常情况(没有异常也没有错误)

小白跟一个同性结婚,这是属于异常情况(在现今社会没有被广泛认可,但是确实存在。)


大概的意思就是,编程里面也是存在‘标签化’的语义。


异常 和 错误 本身就是超越常规程序运行应该处理的结果,我们习惯与把一些表现归类为错误,习惯与另一部分归类为异常。


文末会展示异常的结构树,会再次谈到异常跟错误的关系。


展示一下异常

直接复制下方代码到python REPL终端:


result = 1 / 0
print("result=", result)

运行效果如下:

image.png

看到了吗?


这就是异常,这里的异常是:ZeroDivisionError, 错误消息:division by zero(除零错误!)


错误与异常的关联和更多展示

常见的异常很多,像下面的几种,都非常常见。


ModuleNotFoundError : 通常出现在import leixuewei #导入一个库的时候,这个库不存在则抛出异常!

KeyError: 出席在dict类型的数据取某个键值的时候,比如直接定义一个dict类型的数据,不放入任何键值就取‘leixuewei’这个key,那就会抛出这个错误。

IndexError: 这种就是访问数组或者list列表数据的时候,超出下标,明明一个list就只有2个元素,硬要取第三个元素的时候报错。

ArithmeticError: 上面展示的数值除以0,抛出的异常就是一种,还包括了OeverflowError, FloatingPointError等。

这些错误都非常直观。


这里我们可以打开PyCharm找到Exception类,使用‘find usage’ 查看这个类的子类。


image.png

记住这些异常,其实意义不大。

我们编程更多是需要知道异常的链条和如何使用异常,知道把握这些异常的关联: 继承关系。

下面,我们双击RuntimeError, 马上就发现这个RuntimeError class 后面紧跟了一个NotImplementedError子类。

image.png

那么异常的根源在哪里?

我们继续查找Exception 的父亲BaseException,如下图:

image.png

开发中如何运用异常

灵活运用断言异常,它就挺适合在程序中进行预判的。当然最好的方式是,补充unittest(单元测试)这个在学委之前文章中提到了。

AssertionError 断言异常

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2021/10/23 12:32 下午
# @Author : LeiXueWei
# @CSDN/Juejin/Wechat: 雷学委
# @XueWeiTag: CodingDemo
# @File : assertdemo.py
# @Project : hello
def double(v1):
    result = v1 * 2
    assert result == v1 + v1
    return result
def double_v2(v1):
    result = v1 * 2
    assert result == v1 + 2
    return result
print(double(3))
print(double_v2(3))

运行效果如下:

image.png

这里我们写了一个double(双倍函数),出入一个数字,内部计算应该是2*数字,我们也预期结果为: 数字 + 数字


这种断言异常可以在程序中灵活使用,学委建议不要一下子写几百行代码,而且实现一段逻辑代码的时候适当加上。


比如在做算法类型的题目的时候,加上这个可以有效的辅助程序的完成:有效的中间产生结果校验。


异常处理

Python 提供了语法支持方便我们针对程序异常,按情况进行处理,语法解释如下:


try:
    #运行可能出现异常的函数abc
    abc()
except Exception as e:
    #上述函数abc运行出现异常
    运行一下异常补救的代码或者记录异常
else:
  #abc函数没有发生异常
  运行确认没有异常的代码
finally:
    #不管有没有异常
    print(“总会被执行打印!”)

这里学委写了一段示例代码,可以直接复制运行:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2021/10/24 1:54 下午
# @Author : LeiXueWei
# @CSDN/Juejin/Wechat: 雷学委
# @XueWeiTag: CodingDemo
# @File : trycatchdemo.py
# @Project : hello
def divide(a, b):
    return a / b
result = 100
has_error = False
try:
    data = divide(1, 0) #运行除0函数,会抛出异常
except Exception as e:
    print("error is %s" % e)
    has_error = True
else:
    print("there is no exception")
finally:
    print("always run ")
if not has_error:
    result += data
print("final value %s" % result)

异常捕捉,可以让程序跳过指定异常,继续执行。

如语法介绍那样,正确运行如下图:

image.png

使用try-except语句这不是必要的。


通常我们在应对外部接口或者外部程序调用,外部资源整合的时候,用这个可以有效的保护本程序,跳过外部(别人的)程序错误,继续执行程序,仅此而已。


可以在except 块内放置一些错误处理或者补救代码,比如divide函数还成对等的函数,然后继续后续程序处理。


定义自己的异常,并抛出!

当我们开发一个大型应用的时候,比如Django,我们发现运行这个框架开发的时候,有时候会出现一写Django自带的异常。


这种要如何做?


定义用户自己的异常

通常都是继承RuntimeError类,这类型的异常肯定是运行时异常。


如下:


#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2021/10/24 2:18 下午
# @Author : LeiXueWei
# @CSDN/Juejin/Wechat: 雷学委
# @XueWeiTag: CodingDemo
# @File : userexception.py
# @Project : hello
class DotNotCopyError(RuntimeError):
    def __init__(self, arg):
        self.args = arg
def copy():
    print("抄袭!")
    raise DotNotCopyError("某某抄袭了学委的文章!")
copy()

非常简单,这里也展示了如何抛出异常,我们使用raise关键字加上异常的实例即可。

运行效果如下:

image.png

raise也可以抛出其他内置的异常,可以根据需要在程序中使用。比如程序中检测网络情况,预先抛出异常,帮助运维及早发现外部依赖故障。这个请根据实际情况编写。

延伸思考 - SyntaxError居然也是异常的子类!

image.png

但是这里我们看到SyntaxError也是异常Exception,错误不是跟异常不一样吗?怎么都是同个父亲:Exception。所以严格上来说或Exception不能称为运行时异常,而是部分Exception的子类为运行时异常,因为SyntaxError属于编译解析器解析代码的时候发现的语法错误。


而且SyntaxError是不能够被程序捕捉的。


从这里看,Python的异常机制设计跟Java相比显得比较凌乱了!在Java中异常的根部是Throwable,然后延伸出Error和Exception两个派系,像Error是不能被捕捉,这方面比较清晰。


总结

python的异常,学委总结如下:


image.png

今天1024,学委在此祝愿大家程序不出bug,然后拿捏一切异常!

目录
相关文章
|
运维 监控 算法
时间序列异常检测:MSET-SPRT组合方法的原理和Python代码实现
MSET-SPRT是一种结合多元状态估计技术(MSET)与序贯概率比检验(SPRT)的混合框架,专为高维度、强关联数据流的异常检测设计。MSET通过历史数据建模估计系统预期状态,SPRT基于统计推断判定偏差显著性,二者协同实现精准高效的异常识别。本文以Python为例,展示其在模拟数据中的应用,证明其在工业监控、设备健康管理及网络安全等领域的可靠性与有效性。
1563 13
时间序列异常检测:MSET-SPRT组合方法的原理和Python代码实现
|
人工智能 C# Python
处理python异常
本文介绍了Python中的异常处理机制,并实现了一个简单的异常装饰器。通过`try/except`语句捕获异常,结合`finally`子句完成清理工作。为进一步优化代码结构,文章提出了使用装饰器处理异常的方法,避免函数中大量冗长的异常处理语句。通过类封装异常装饰器,多个函数可共享异常处理逻辑,提升代码简洁性和可维护性。总结强调了装饰器在异常处理中的优势,使代码更加优雅高效。
367 27
|
人工智能 Shell 开发工具
[oeasy]python065python报错怎么办_try_试着来_except_发现异常
本文介绍了Python中处理异常的基本方法,重点讲解了`try`和`except`的用法。通过一个计算苹果重量的小程序示例,展示了如何捕获用户输入错误并进行处理。主要内容包括: 1. **回顾上次内容**:简要回顾了Shell环境、Python3游乐场和Vim编辑器的使用。 2. **编写程序**:编写了一个简单的程序来计算苹果的总重量,但发现由于输入类型问题导致结果错误。 3. **调试与修正**:通过调试发现输入函数返回的是字符串类型,需要将其转换为整数类型才能正确计算。
551 32
如何处理python的常见异常问题
在Python语言中,python异常处理机制主要依赖try、except、else、finally和raise五个关键字。本篇文章将为大家详细讲解一下如何处理python的常见异常问题。
|
数据库 Python
[oeasy]python066_如何捕获多个异常_try_否则_else_exception
本文介绍了Python中`try...except...else`结构的使用方法。主要内容包括: 1. **回顾上次内容**:简要复习了`try`和`except`的基本用法,强调了异常处理的重要性。 2. **详细解释**: - `try`块用于尝试执行代码,一旦发现错误会立即终止并跳转到`except`块。 - `except`块用于捕获特定类型的异常,并进行相应的处理。 - `else`块在没有异常时执行,是可选的。 3. **示例代码**:通过具体例子展示了如何捕获不同类型的异常(如`ValueError`和`ZeroDivisionError`),并解释了异常处理
376 24
|
存储 索引 Python
Python生成器、装饰器、异常(2)
【10月更文挑战第16天】
371 1
Python生成器、装饰器、异常(2)
|
测试技术 开发者 Python
对于Python中的异常要如何处理,raise关键字你真的了解吗?一篇文章带你从头了解
`raise`关键字在Python中用于显式引发异常,允许开发者在检测到错误条件时中断程序流程,并通过异常处理机制(如try-except块)接管控制。`raise`后可跟异常类型、异常对象及错误信息,适用于验证输入、处理错误、自定义异常、重新引发异常及测试等场景。例如,`raise ValueError("Invalid input")`用于验证输入数据,若不符合预期则引发异常,确保数据准确并提供清晰错误信息。此外,通过自定义异常类,可以针对特定错误情况提供更具体的信息,增强代码的健壮性和可维护性。
|
Python
在Python中,`try...except`语句用于捕获和处理程序运行时的异常
在Python中,`try...except`语句用于捕获和处理程序运行时的异常
572 5
|
Python
在Python中,自定义函数可以抛出自定义异常
在Python中,自定义函数可以抛出自定义异常
457 5
|
存储 开发者 Python
自定义Python的异常
自定义Python的异常
395 5

推荐镜像

更多