1.1 异常是什么

python使用异常对象来表示异常状态,并在遇到错误时引发异常。异常对象未被处理,程序将终止并显示一条错误信息。

我们可以通过各种方法引发和捕获错误,并采取对应措施。

1.2 将“错误”变成异常

自主地引发异常

1.2.1 raise语句

我们通过预测异常可能发生的位置,通过raise语句主动抛出异常,用except语句来接收前面出现的异常,并作出对应的操作

def divide(x, y):
if y == 0:
# 引出异常
raise ZeroDivisionError("Division by zero!")
else:
return x / y # 测试
try:
result = divide(6, 0)
# 接收异常
except ZeroDivisionError as ex:
print(f"Error: {str(ex)}")
else:
print(result)
> Error: Division by zero!

一些常见的内置异常类

Exception   # 几乎所有异常类均由这个派生而来
AttributeError 试图访问一个对象没有的树形,比如foo.x,但是foo没有属性x
IOError 输入/输出异常;基本上是无法打开文件
ImportError 无法引入模块或包;基本上是路径问题或名称错误
IndentationError 语法错误(的子类) ;代码没有正确对齐
IndexError 下标索引超出序列边界,比如当x只有三个元素,却试图访问x[5]
KeyError 试图访问字典里不存在的键
KeyboardInterrupt Ctrl+C被按下
NameError 使用一个还未被赋予对象的变量
SyntaxError Python代码非法,代码不能编译(个人认为这是语法错误,写错了)
TypeError 传入对象类型与要求的不符合

1.3 自定义的异常类

首先,要直接或间接地继承Exception

格式

class 异常类名(Exception):
pass

利用自定义的异常类对1.2中的例子进行改进

class MyException(Exception):  # 自定义异常类
pass def divide(x, y):
if y == 0:
raise MyException("Division by zero!")
else:
return x / y # 测试
try:
result = divide(6, 0)
except MyException as ex:
print(f"Error: {str(ex)}")
else:
print(result)

1.3.1一个具体使用场景

检查用户输入的邮件格式,不对则报错

class InvalidEmailException(Exception):
def __init__(self, email):
self.email = email
self.message = f"{email} is not a valid email address. Please try again."
super().__init__(self.message) def send_email(to, subject, body):
if "@" not in to:
raise InvalidEmailException(to) # 抛出异常
print(f"Email sent to {to} with subject '{subject}' and body '{body}'.") # 测试
try:
send_email("invalid-email", "Test email", "This is a test email.")
except InvalidEmailException as ex:
print(f"Error: {ex.message}")

第五行super().__init__(self.message) 调用基类 Exception 的构造函数来初始化 self.message

Exception的构造函数:

class Exception(BaseException):
def __init__(self, *args: object) -> None:
"""
Initialize self. See help(type(self)) for accurate signature.
"""
pass

构造函数接受可变长度的参数 *args,但是它并没有执行任何实际操作,只是一个空的 pass 语句。这意味着,我们可以在自定义异常类的构造函数中调用父类 Exception 的构造函数,同时传递自定义的错误消息作为参数。

关于第五行的作用:

  • 第5行的作用只是使用基类 Exception 的构造函数,来完成可能会影响异常的某些其他行为,如设置异常的堆栈跟踪信息等。这些信息可以帮助程序员更轻松地找到代码中发生异常的位置。

    因此,虽然第5行实际上不是非常必要,但它是一个良好的实践,可以帮助进一步丰富异常信息。

  • 个人认为,可以通过重写Exception的构造函数

  • 猜想:可能会定义多个自定义类,通过定义Exception参数的方式,进行类之间的异常信息传递

1.3.2 同时监测多种异常

将异常类型以元组形式展现(没有采用raise,等待程序抛出异常并接收)

class CustomException(Exception):
def __init__(self, message):
super().__init__(message) # 与上个程序第五行同理 # 若出现异常,则要求用户重新输入
while True:
try:
# 获取用户输入的除数和被除数
divisor = int(input("Enter the divisor: "))
dividend = int(input("Enter the dividend: "))
result = dividend / divisor
# 通过元组进行多种异常监测
except (ZeroDivisionError, TypeError, ValueError) as ex:
# 捕获多种异常
print(ex)
else:
print(f"The result of division is: {result}")
break # 成功即跳出循环

运行结果

Enter the divisor: 0
Enter the dividend: 1
division by zero
Enter the divisor: we
invalid literal for int() with base 10: 'we'
Enter the divisor: 2
Enter the dividend: 1
The result of division is: 0.5

1.3.3 一网打尽的异常和else

同时监测多个异常可能不够,可以一网打尽

# 若出现异常,则要求用户重新输入
while True:
try:
# 获取用户输入的除数和被除数
divisor = int(input("Enter the divisor: "))
dividend = int(input("Enter the dividend: "))
result = dividend / divisor
# 通过元组进行多种异常监测
except Exception as ex:
#对所有Exception的子类异常进行监测,只有发生了对应的子类异常,才会被捕获
# 捕获多种异常
print(ex)
else: # 通过else语句实现循环,这里是except语句的else, 当不执行except语句时,执行else
print(f"The result of division is: {result}")
break # 成功即跳出循环

运行结果

Enter the divisor: er
invalid literal for int() with base 10: 'er'
Enter the divisor: 0
Enter the dividend: 1
division by zero
Enter the divisor: 1
Enter the dividend: 2
The result of division is: 2.0

tip:

在编写代码时,最好不要捕获所有异常类型。我们应该尽可能地特定地捕获那些预期的、已知的异常类型,并将其他异常类型传递给更高层的异常处理机制进行处理。这样可以更加有效地调试和解决问题,而且代码更加可读和可维护。

1.3.4 最后的finally

无论是否发生异常,finally语句均会运行。多用于执行清理工作。

如:关闭文件,关闭网络套接字等

try:
1 / 2
except NameError:
print("Unknown wariable")
else:
print('That went well')
finally:
print('Cleaning up.')

运行结果

That went well
Cleaning up.

1.3.5 异常的传递

如果不处理函数中引发的异常,它将向上传播到调用函数中,直到主程序,若主程序中还是不能处理异常,程序将通知并显示站跟踪信息。

def faulty():
raise Exception("wrong") def ig_exception():
faulty() def hl_exception():
try:
faulty()
except:
print('Exception handled')
ig_exception()

运行结果:打印了栈跟踪信息和异常信息

Traceback (most recent call last):
File "d:\M\github\Python\Demo\t12.py", line 12, in <module>
ig_exception()
File "d:\M\github\Python\Demo\t12.py", line 5, in ig_exception
faulty()
File "d:\M\github\Python\Demo\t12.py", line 2, in faulty
raise Exception("wrong")
Exception: wrong

若是只调用hl_exception() 异常会被处理,程序不会终止

hl_exception()
print("hello") # 打印出结果,说明程序未终止,仍在运行
> Exception handled
> hello

1.4 异常之禅

  • 除了使用try/except语句来处理异常外,还可以使用if/else语句,只是不推荐这样做
  • 可以检查对象是否包含特定的属性
try:
obj.write
except AttributeError:
print('The object is not worteable')
else:
print('The object is writeable')
  • 不那么异常的时候,可以发出警告,由模块warning 中的函数warn提供
from warnings import warn
warn('got a bad feeling.')
print('hello') # 可以打印,说明程序仍在运行
>
d:\M\github\Python\Demo\t12.py:2: UserWarning: got a bad feeling.
warn('got a bad feeling.')
hello

python学习笔记:第九章异常的更多相关文章

  1. 【python学习笔记】8.异常

    [python学习笔记]8.异常 raise Exception: 抛出指定异常 try/except: 捕捉异常 except: 第一个参数是需要捕获的异常类型,可以是多个类型组成元组,第二个参数是 ...

  2. 《机器学习实战》学习笔记第九章 —— 决策树之CART算法

    相关博文: <机器学习实战>学习笔记第三章 —— 决策树 主要内容: 一.CART算法简介 二.分类树 三.回归树 四.构建回归树 五.回归树的剪枝 六.模型树 七.树回归与标准回归的比较 ...

  3. o'Reill的SVG精髓(第二版)学习笔记——第九章

    第九章:文本 9.1 字符:在XML文档中,字符是指带有一个数字值的一个或多个字节,数字只与Unicode标准对应. 符号:符号(glyph)是指字符的视觉呈现.每个字符都可以用很多不同的符号来呈现. ...

  4. 《Python基础教程(第二版)》学习笔记 -> 第九章 魔法方法、属性和迭代器

    准备工作 >>> class NewStyle(object): more_code_here >>> class OldStyle: more_code_here ...

  5. Python学习笔记:07异常

    异常 Python用异常对象(Exception Object)来表示异常情况,当异常未被捕获时,就会产生回溯(Traceback) 异常分类 內建异常类:Exception,AttributeErr ...

  6. python学习笔记(七)、异常

    在实际开发中,往往不会出现一个系统编写下来,没有出现任何一个bug.为处理这种会出现错误的地方,如除数为零的除法,python提供了非常强大的机制————异常处理机制. 1 异常 python使用异常 ...

  7. Python学习笔记 -- 第一章

    本笔记参考廖雪峰的Python教程 简介 Python是一种计算机高级程序设计语言. 用Python可以做什么? 可以做日常任务,比如自动备份你的MP3:可以做网站,很多著名的网站包括YouTube就 ...

  8. Python学习笔记第九周

    目录: 一.基础概念 1.paramiko模块 2.进程与线程 1.进程 2.线程 3.进程与线程的区别 4.Python GIL 5.thread模块 6.Join与Daemon 7.线程锁(Mut ...

  9. python学习笔记十:异常

    一.语法 #!/usr/bin/python filename='hello' #try except finally demo try: open('abc.txt') print hello ex ...

  10. 学习笔记 第九章 使用CSS美化表格

    第9章  使用CSS美化表格 学习重点 正确使用表格标签: 设置表格和单元格属性: 设计表格的CSS样式. 9.1 表格的基本结构 表格由行.列.单元格3部分组成,单元格时行与列交叉的部分. 在HTM ...

随机推荐

  1. 由 Base64 展开的知识探讨

    我们是袋鼠云数栈 UED 团队,致力于打造优秀的一站式数据中台产品.我们始终保持工匠精神,探索前端道路,为社区积累并传播经验价值.. 本文作者:霜序(掘金) 前言 在我们的业务应用中越来越多的应用到编 ...

  2. JVM的内存分配及各种常量池的区别(静态常量池、运行时常量池、字符串常量池)

    JVM内存分配 先了解下JVM中的内存分配,此处以hotspot vm为例(官方jdk采用的vm) 程序计数器 栈 1. 虚拟机栈 2. 本地方法栈 Java堆 堆内存是各个线程共享的区域 方法区 它 ...

  3. Docker快速部署Hadoop环境

    文章目录 安装环境 安装过程 拉取镜像 在Docker中创建网络,方便通信 创建Master节点 创建slave1和slave2节点 分别进入三个容器修改hosts文件 在Master执行集群初始化 ...

  4. MySQL WorkBench更换界面成中文的方法

    菜单页面更换 文章目录 菜单页面更换 汉化文件的xml文件我放在下面的网盘中了 1.找到MySQL的安装位置, 总结 汉化文件的xml文件我放在下面的网盘中了 1.找到MySQL的安装位置, 具体安装 ...

  5. Microsoft Loop初体验

    目前AI copilot无法使用. 问题 图片 在设置中可以打开实验选项 简单开箱使用 很多人说微软的loop竞品是notion,那么作为卡片盒双链笔记软件,最热门的应用当然是notion.从loop ...

  6. 【漏洞分析】ReflectionToken BEVO代币攻击事件分析

    前言 BEVO代币是一种Reflection Token(反射型代币),并且拥有通缩的特性.关于Reflection Token更为详细的说明可参考这篇文章.然后目前浏览到的很多分析报告没有指出其漏洞 ...

  7. #Powerbi 利用EOMONTH,计算月度时间进度

    在POWERBI中计算本月的时间进度 许多小伙伴在做看板时,往往会遇到需要时间进度的计算,来配合业绩达成的进度,进行比较分析.那么如何在BI做通过公式进行这个数据的求值呢? 首先,我们需要测算两个值, ...

  8. 2021-07-14:接雨水。给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。

    2021-07-14:接雨水.给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水. 福大大 答案2021-07-14: 左右指针向中间移动.左指针是左边柱 ...

  9. Anaconda网址

    Anaconda: python全家桶,之前还有32位,现在需要64位. 官方网址:https://www.anaconda.com/ 国内源:https://mirrors.tuna.tsinghu ...

  10. IntelliJ IDEA一站式配置【全】(提高开发效率)

    IDEA常用设置(提高开发效率) 本人也是IDEA编译器的忠实用户了,但是有时出于各种原因,比如更换设备等等,IDEA总是需要重新安装配置.这就让我比较苦恼,因为总是记不全自己之前都修改了哪些地方(原 ...