python学习笔记:第九章异常

这篇具有很好参考价值的文章主要介绍了python学习笔记:第九章异常。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

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() 异常会被处理,程序不会终止文章来源地址https://www.toymoban.com/news/detail-554505.html

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学习笔记:第九章异常的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 红宝石阅读笔记--第九章 代理与反射

    1. 代理中的 this 这是因为 User 实例一开始使用目标对象作为 WeakMap 的键,代理对象却尝试从自身取得这个实 例。要解决这个问题,就需要重新配置代理,把代理 User 实例改为代理 User 类本身。之后再创建代 理的实例就会以代理实例作为 WeakMap 的键了: 刚开始自己不懂什么意

    2024年02月11日
    浏览(38)
  • go 笔记 第九章 结构体 struct 声明和使用

    package main import “fmt” type qm struct { name string age int hobby []string home } type home struct { address string } // 给结构体声明方法 func (q qm) song(name string) (ret string) { ret = “惊雷” fmt.Printf(“%v—%v–%v”, q.name, name, q.age) fmt.Println() return ret } func (h home) open() { fmt.Println(“open”) } func main() { v

    2024年02月16日
    浏览(44)
  • Rust in Action笔记 第九章 时间管理

    本章主要讲如何实现一个网络时间协议NTP(Network Time Protocol)客户端,谷歌的世界时间同步误差大概在7毫秒,开源网站CockroachDB的延迟在数十毫秒,使用了NTP协议,在处理与时间敏感的数据时, chrono 库成为了事实上的标准库; 由于潮汐影响和地球转矩的问题,事实上每一秒

    2024年02月12日
    浏览(73)
  • 华为HCIA课堂笔记第九章 STP生成树

    选举一个根桥(根交换机) 每一个非根桥上选举一个根端口(去往根桥最近的端口) 在每一个链路上选举一个指定端口(向树的下游转发数据) 阻塞剩余的非根端口,非指定端口。 根桥:生成树的树根 通过比较桥ID(称为BID),选择所有的相连二层设备中的桥 ID,越小越优

    2024年01月22日
    浏览(44)
  • Python第九章作业(初级)

    目录 第1关:统计字母数量 第2关:统计文章字符数 第3关:查询高校信息 第4关:查询高校名 第5关:通讯录读取 第6关:JSON转列表 第7关:利用数据文件统计成绩 第8关:研究生录取数据分析A 第9关:图书数据分析(A) 第1关:统计字母数量 读取附件是一篇英文短文,请编写

    2024年02月07日
    浏览(99)
  • Python之第九章 内置模块

    目录 第九章 内置模块 1.math模块 1.查看: 2.常用方法: 2.random模块 1.查看: ​2.例: 3.random(a,b) 4.random.sample(range(0,20),10) 3.os模块与os.path模块 1.作用 2.目录 3.os模块与操作系统的关系 4.路径 5.判断目录是否存在 6.创建目录 7.删除目录 8.文件或目录的重命名 9.获取文件信息 10.常见

    2024年02月11日
    浏览(33)
  • 《C和指针》读书笔记(第九章 字符串、字符和字节)

    在C语言中,字符串和数组有很多相似之处,且官方提供了很多的库函数可供调用。那么字符串和数组这对姐妹花,究竟有着什么样的亲密关系,而作为我们本期的重点角色,字符串又有何独特之处呢? C语言并没有显式的字符串数据类型,因为字符串以字符串常量的形式出现

    2024年02月08日
    浏览(46)
  • 【Rust】Rust学习 第九章错误处理

    Rust 将错误组合成两个主要类别: 可恢复错误 ( recoverable )和  不可恢复错误 ( unrecoverable )。可恢复错误通常代表向用户报告错误和重试操作是合理的情况,比如未找到文件。不可恢复错误通常是 bug 的同义词,比如尝试访问超过数组结尾的位置。 大部分语言并不区分这

    2024年02月13日
    浏览(38)
  • 信息安全概论复习笔记 第九章 身份认证(不是重点,做了解吧)

    身份认证(Authentication)的定义: 宣称者向验证方出示证据,证明其身份的交互过程 至少涉及两个参与者,是一种协议 分为双向认证和单向认证 身份认证并不是一种静态的加密,而是一个 协议过程 区分两个概念 身份认证和报文鉴别 区别: ①报文鉴别是静态附加在报文之

    2024年02月02日
    浏览(36)
  • 系统集成项目管理工程师 笔记(第九章:项目成本管理)

    9.1 成本管理概念及相关术语 9.1.1 成本与成本管理概念 项目成本概念及其构成 在项目中, 成本 是指项目活动或其组成部分的货币价值或价格,包括为实施、完成或创造该活动或其组成部分所需资源的货币价值。具体的成本一般包括直接工时、其他直接费用、间接工时、其他

    2024年02月01日
    浏览(47)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包