【Python】错误&异常

打印 上一主题 下一主题

主题 971|帖子 971|积分 2915


   个人主页:Guiat
归属专栏:Python

  


  
正文
1. 错误和异常的概念

1.1 错误

在 Python 里,错误一般可分为语法错误和逻辑错误。


  • 语法错误:是指代码编写不符合 Python 语法规则,导致 Python 表明器无法正确解析代码。例如,少了冒号、括号不匹配等。
  1. # 语法错误示例,if 语句后缺少冒号
  2. if True
  3.     print("This is a syntax error.")
复制代码


  • 逻辑错误:代码语法上没有问题,但程序运行结果不符合预期。这通常是由于算法设计错误、变量使用不当等缘故原由造成的。例如,在计算匀称值时,分母大概为 0。
1.2 异常

异常是在程序运行过程中出现的错误事件,它会打断程序的正常执行流程。Python 有许多内置异常范例,如 ZeroDivisionError、IndexError 等。
2. 常见的内置异常范例

2.1 ZeroDivisionError

当试图用一个数除以 0 时,会引发该异常。
  1. try:
  2.     result = 5 / 0
  3. except ZeroDivisionError:
  4.     print("不能除以零!")
复制代码
2.2 IndexError

当使用的索引超出序列(如列表、元组)的有用范围时,会触发此异常。
  1. my_list = [1, 2, 3]
  2. try:
  3.     print(my_list[3])
  4. except IndexError:
  5.     print("索引超出范围!")
复制代码
2.3 KeyError

在字典中使用不存在的键进行访问时,会抛出 KeyError。
  1. my_dict = {'a': 1, 'b': 2}
  2. try:
  3.     print(my_dict['c'])
  4. except KeyError:
  5.     print("键不存在!")
复制代码
2.4 TypeError

当操作或函数应用于不得当范例的对象时,会引发该异常。例如,将字符串和整数相加。
  1. try:
  2.     result = "hello" + 1
  3. except TypeError:
  4.     print("类型不匹配,不能将字符串和整数相加!")
复制代码
3. 异常处置惩罚机制

3.1 try-except 语句

try-except 语句用于捕获和处置惩罚异常。try 块中放置大概会引发异常的代码,except 块用于处置惩罚捕获到的异常。
  1. try:
  2.     num1 = int(input("请输入一个整数: "))
  3.     num2 = int(input("请输入另一个整数: "))
  4.     result = num1 / num2
  5.     print(f"结果是: {result}")
  6. except ValueError:
  7.     print("输入不是有效的整数!")
  8. except ZeroDivisionError:
  9.     print("不能除以零!")
复制代码
3.2 try-except-else 语句

else 块在 try 块中的代码没有引发异常时执行。
  1. try:
  2.     num = int(input("请输入一个整数: "))
  3. except ValueError:
  4.     print("输入不是有效的整数!")
  5. else:
  6.     print(f"你输入的整数是: {num}")
复制代码
3.3 try-except-finally 语句

finally 块无论 try 块中是否发生异常,都会被执行。常用于释放资源等操作。
  1. file = None
  2. try:
  3.     file = open("test.txt", "r")
  4.     content = file.read()
  5.     print(content)
  6. except FileNotFoundError:
  7.     print("文件未找到!")
  8. finally:
  9.     if file:
  10.         file.close()
复制代码
4. 异常的抛出

4.1 raise 语句

可以使用 raise 语句手动抛出异常。例如,自定义一个异常类,并在满足特定条件时抛出该异常。
  1. class CustomError(Exception):
  2.     pass
  3. def check_number(num):
  4.     if num < 0:
  5.         raise CustomError("输入的数字不能为负数!")
  6.     return num
  7. try:
  8.     result = check_number(-5)
  9. except CustomError as e:
  10.     print(e)
复制代码
4.2 异常链

在抛出一个异常时,可以使用 raise ... from ... 语句将当前异常与另一个异常关联起来,形成异常链。
  1. try:
  2.     num = int("abc")
  3. except ValueError as original_exception:
  4.     raise CustomError("输入无法转换为整数!") from original_exception
复制代码
5. 自定义异常

5.1 定义自定义异常类

通过继承内置的 Exception 类或其子类,可以创建自定义异常类。
  1. class MyCustomError(Exception):
  2.     def __init__(self, message):
  3.         self.message = message
  4.         super().__init__(self.message)
复制代码
5.2 使用自定义异常

在代码中可以像使用内置异常一样使用自定义异常。
  1. def validate_age(age):
  2.     if age < 0:
  3.         raise MyCustomError("年龄不能为负数!")
  4.     return age
  5. try:
  6.     valid_age = validate_age(-3)
  7. except MyCustomError as e:
  8.     print(e.message)
复制代码
6. 异常的捕获顺序与多异常捕获

6.1 异常捕获顺序

在使用多个 except 子句时,Python 会按照 except 子句的顺序依次查抄捕获的异常范例。一旦匹配到相应的异常范例,就会执行该 except 子句中的代码,并且不会再继承查抄后续的 except 子句。因此,捕获范围小的异常应该放在前面,捕获范围大的异常放在后面。
  1. try:
  2.     num = int("abc")
  3.     result = 1 / num
  4. except ValueError:
  5.     print("输入无法转换为整数!")
  6. except ZeroDivisionError:
  7.     print("不能除以零!")
  8. except Exception:
  9.     print("发生了其他未知异常!")
复制代码
在上述代码中,ValueError 捕获范围相对较小,先辈行查抄。假如输入无法转换为整数,就会执行对应的 except 子句。假如没有匹配到 ValueError,再查抄 ZeroDivisionError 等其他异常。
6.2 多异常捕获

可以在一个 except 子句中捕获多种不同范例的异常,使用元组将这些异常范例括起来。
  1. try:
  2.     num = int("abc")
  3.     result = 1 / num
  4. except (ValueError, ZeroDivisionError):
  5.     print("输入错误或者进行了除以零的操作!")
复制代码
这种方式实用于不同异常范例需要执行相同处置惩罚逻辑的情况。
7. 异常信息的获取

7.1 获取异常对象

在 except 子句中,可以通过给异常范例后面指定一个变量名来获取异常对象,从而访问异常的相干信息,如异常的错误消息。
  1. try:
  2.     num = int("abc")
  3. except ValueError as ve:
  4.     print(f"捕获到 ValueError 异常,错误信息: {ve}")
复制代码
在上述代码中,ve 就是捕获到的 ValueError 异常对象,通过它可以获取具体的错误消息。
7.2 异常对象的属性和方法

不同的异常范例大概有不同的属性和方法。例如,OSError 异常通常会包含有关操作系统错误的具体信息,如错误号和错误消息。
  1. import os
  2. try:
  3.     file = open("nonexistent_file.txt", "r")
  4. except OSError as oe:
  5.     print(f"错误号: {oe.errno}")
  6.     print(f"错误消息: {oe.strerror}")
复制代码
这里通过 oe.errno 获取错误号,通过 oe.strerror 获取具体的错误消息。
8. 异常处置惩罚的最佳实践

8.1 正确捕获异常

尽量正确地捕获特定范例的异常,而不是使用通用的 except 子句捕获所有异常。这样可以更清晰地处置惩罚不同范例的错误,制止隐蔽潜伏的问题。
  1. try:
  2.     num = int("abc")
  3. except ValueError:
  4.     print("输入无法转换为整数!")
复制代码
而不是:
  1. try:
  2.     num = int("abc")
  3. except:
  4.     print("发生了异常!")
复制代码
8.2 异常处置惩罚的粒度

异常处置惩罚的粒度要适中。假如粒度太粗,大概会掩盖一些紧张的错误信息;假如粒度太细,会使代码变得复杂。例如,在一个函数中,对于不同的操作可以分别进行异常处置惩罚。
  1. def process_data():
  2.     try:
  3.         # 读取数据的操作
  4.         data = read_data()
  5.     except FileNotFoundError:
  6.         print("数据文件未找到!")
  7.         return
  8.     try:
  9.         # 处理数据的操作
  10.         result = analyze_data(data)
  11.     except ValueError:
  12.         print("数据处理过程中发生值错误!")
  13.         return
  14.     return result
复制代码
8.3 资源管理与异常处置惩罚

在处置惩罚需要手动释放资源(如文件、网络连接等)的情况时,要确保资源在异常发生时也能被正确释放。可以使用 try - finally 语句或 with 语句。with 语句是一种更简洁、更安全的资源管理方式,它会自动处置惩罚资源的获取和释放。
  1. with open("test.txt", "r") as file:
  2.     content = file.read()
  3.     print(content)
  4. # 无需手动调用 file.close(),with 语句会自动处理
复制代码
9. 异常在模块和类中的应用

9.1 模块中的异常处置惩罚

在模块中,通常会定义一些函数供其他模块调用。在这些函数中,要公道处置惩罚大概出现的异常,并根据情况将异常抛出给调用者。
  1. # module.py
  2. def divide_numbers(a, b):
  3.     if b == 0:
  4.         raise ZeroDivisionError("除数不能为零!")
  5.     return a / b
复制代码
  1. # main.py
  2. import module
  3. try:
  4.     result = module.divide_numbers(5, 0)
  5. except ZeroDivisionError as zde:
  6.     print(zde)
复制代码
9.2 类中的异常处置惩罚

在类的方法中,也需要进行异常处置惩罚。可以根据类的功能和使用场景,自定义异常类并在符合的时间抛出。
  1. class BankAccount:
  2.     def __init__(self, balance):
  3.         if balance < 0:
  4.             raise ValueError("账户余额不能为负数!")
  5.         self.balance = balance
  6.     def withdraw(self, amount):
  7.         if amount > self.balance:
  8.             raise ValueError("取款金额超过账户余额!")
  9.         self.balance -= amount
  10.         return self.balance
  11. try:
  12.     account = BankAccount(-10)
  13. except ValueError as ve:
  14.     print(ve)
  15. try:
  16.     valid_account = BankAccount(100)
  17.     valid_account.withdraw(200)
  18. except ValueError as ve:
  19.     print(ve)
复制代码
在上述代码中,BankAccount 类的初始化方法和 withdraw 方法都进行了异常处置惩罚,确保对象的状态和操作的正当性。
结语
感谢您的阅读!期待您的一键三连!欢迎指正!


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

拉不拉稀肚拉稀

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表