当前位置: 首页 > article >正文

【Python】错误异常

在这里插入图片描述

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

在这里插入图片描述

文章目录

  • 1. 错误和异常的概念
    • 1.1 错误
    • 1.2 异常
  • 2. 常见的内置异常类型
    • 2.1 `ZeroDivisionError`
    • 2.2 `IndexError`
    • 2.3 `KeyError`
    • 2.4 `TypeError`
  • 3. 异常处理机制
    • 3.1 `try-except` 语句
    • 3.2 `try-except-else` 语句
    • 3.3 `try-except-finally` 语句
  • 4. 异常的抛出
    • 4.1 `raise` 语句
    • 4.2 异常链
  • 5. 自定义异常
    • 5.1 定义自定义异常类
    • 5.2 使用自定义异常
  • 6. 异常的捕获顺序与多异常捕获
    • 6.1 异常捕获顺序
    • 6.2 多异常捕获
  • 7. 异常信息的获取
    • 7.1 获取异常对象
    • 7.2 异常对象的属性和方法
  • 8. 异常处理的最佳实践
    • 8.1 精确捕获异常
    • 8.2 异常处理的粒度
    • 8.3 资源管理与异常处理
  • 9. 异常在模块和类中的应用
    • 9.1 模块中的异常处理
    • 9.2 类中的异常处理

正文

1. 错误和异常的概念

1.1 错误

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

  • 语法错误:是指代码编写不符合 Python 语法规则,导致 Python 解释器无法正确解析代码。例如,少了冒号、括号不匹配等。
# 语法错误示例,if 语句后缺少冒号
if True
    print("This is a syntax error.")
  • 逻辑错误:代码语法上没有问题,但程序运行结果不符合预期。这通常是由于算法设计错误、变量使用不当等原因造成的。例如,在计算平均值时,分母可能为 0。

1.2 异常

异常是在程序运行过程中出现的错误事件,它会打断程序的正常执行流程。Python 有许多内置异常类型,如 ZeroDivisionErrorIndexError 等。

2. 常见的内置异常类型

2.1 ZeroDivisionError

当试图用一个数除以 0 时,会引发该异常。

try:
    result = 5 / 0
except ZeroDivisionError:
    print("不能除以零!")

2.2 IndexError

当使用的索引超出序列(如列表、元组)的有效范围时,会触发此异常。

my_list = [1, 2, 3]
try:
    print(my_list[3])
except IndexError:
    print("索引超出范围!")

2.3 KeyError

在字典中使用不存在的键进行访问时,会抛出 KeyError

my_dict = {'a': 1, 'b': 2}
try:
    print(my_dict['c'])
except KeyError:
    print("键不存在!")

2.4 TypeError

当操作或函数应用于不适当类型的对象时,会引发该异常。例如,将字符串和整数相加。

try:
    result = "hello" + 1
except TypeError:
    print("类型不匹配,不能将字符串和整数相加!")

3. 异常处理机制

3.1 try-except 语句

try-except 语句用于捕获和处理异常。try 块中放置可能会引发异常的代码,except 块用于处理捕获到的异常。

try:
    num1 = int(input("请输入一个整数: "))
    num2 = int(input("请输入另一个整数: "))
    result = num1 / num2
    print(f"结果是: {result}")
except ValueError:
    print("输入不是有效的整数!")
except ZeroDivisionError:
    print("不能除以零!")

3.2 try-except-else 语句

else 块在 try 块中的代码没有引发异常时执行。

try:
    num = int(input("请输入一个整数: "))
except ValueError:
    print("输入不是有效的整数!")
else:
    print(f"你输入的整数是: {num}")

3.3 try-except-finally 语句

finally 块无论 try 块中是否发生异常,都会被执行。常用于释放资源等操作。

file = None
try:
    file = open("test.txt", "r")
    content = file.read()
    print(content)
except FileNotFoundError:
    print("文件未找到!")
finally:
    if file:
        file.close()

4. 异常的抛出

4.1 raise 语句

可以使用 raise 语句手动抛出异常。例如,自定义一个异常类,并在满足特定条件时抛出该异常。

class CustomError(Exception):
    pass

def check_number(num):
    if num < 0:
        raise CustomError("输入的数字不能为负数!")
    return num

try:
    result = check_number(-5)
except CustomError as e:
    print(e)

4.2 异常链

在抛出一个异常时,可以使用 raise ... from ... 语句将当前异常与另一个异常关联起来,形成异常链。

try:
    num = int("abc")
except ValueError as original_exception:
    raise CustomError("输入无法转换为整数!") from original_exception

5. 自定义异常

5.1 定义自定义异常类

通过继承内置的 Exception 类或其子类,可以创建自定义异常类。

class MyCustomError(Exception):
    def __init__(self, message):
        self.message = message
        super().__init__(self.message)

5.2 使用自定义异常

在代码中可以像使用内置异常一样使用自定义异常。

def validate_age(age):
    if age < 0:
        raise MyCustomError("年龄不能为负数!")
    return age

try:
    valid_age = validate_age(-3)
except MyCustomError as e:
    print(e.message)

6. 异常的捕获顺序与多异常捕获

6.1 异常捕获顺序

在使用多个 except 子句时,Python 会按照 except 子句的顺序依次检查捕获的异常类型。一旦匹配到相应的异常类型,就会执行该 except 子句中的代码,并且不会再继续检查后续的 except 子句。因此,捕获范围小的异常应该放在前面,捕获范围大的异常放在后面。

try:
    num = int("abc")
    result = 1 / num
except ValueError:
    print("输入无法转换为整数!")
except ZeroDivisionError:
    print("不能除以零!")
except Exception:
    print("发生了其他未知异常!")

在上述代码中,ValueError 捕获范围相对较小,先进行检查。如果输入无法转换为整数,就会执行对应的 except 子句。如果没有匹配到 ValueError,再检查 ZeroDivisionError 等其他异常。

6.2 多异常捕获

可以在一个 except 子句中捕获多种不同类型的异常,使用元组将这些异常类型括起来。

try:
    num = int("abc")
    result = 1 / num
except (ValueError, ZeroDivisionError):
    print("输入错误或者进行了除以零的操作!")

这种方式适用于不同异常类型需要执行相同处理逻辑的情况。

7. 异常信息的获取

7.1 获取异常对象

except 子句中,可以通过给异常类型后面指定一个变量名来获取异常对象,从而访问异常的相关信息,如异常的错误消息。

try:
    num = int("abc")
except ValueError as ve:
    print(f"捕获到 ValueError 异常,错误信息: {ve}")

在上述代码中,ve 就是捕获到的 ValueError 异常对象,通过它可以获取具体的错误消息。

7.2 异常对象的属性和方法

不同的异常类型可能有不同的属性和方法。例如,OSError 异常通常会包含有关操作系统错误的详细信息,如错误号和错误消息。

import os

try:
    file = open("nonexistent_file.txt", "r")
except OSError as oe:
    print(f"错误号: {oe.errno}")
    print(f"错误消息: {oe.strerror}")

这里通过 oe.errno 获取错误号,通过 oe.strerror 获取具体的错误消息。

8. 异常处理的最佳实践

8.1 精确捕获异常

尽量精确地捕获特定类型的异常,而不是使用通用的 except 子句捕获所有异常。这样可以更清晰地处理不同类型的错误,避免隐藏潜在的问题。

try:
    num = int("abc")
except ValueError:
    print("输入无法转换为整数!")

而不是:

try:
    num = int("abc")
except:
    print("发生了异常!")

8.2 异常处理的粒度

异常处理的粒度要适中。如果粒度太粗,可能会掩盖一些重要的错误信息;如果粒度太细,会使代码变得复杂。例如,在一个函数中,对于不同的操作可以分别进行异常处理。

def process_data():
    try:
        # 读取数据的操作
        data = read_data()
    except FileNotFoundError:
        print("数据文件未找到!")
        return
    try:
        # 处理数据的操作
        result = analyze_data(data)
    except ValueError:
        print("数据处理过程中发生值错误!")
        return
    return result

8.3 资源管理与异常处理

在处理需要手动释放资源(如文件、网络连接等)的情况时,要确保资源在异常发生时也能被正确释放。可以使用 try - finally 语句或 with 语句。with 语句是一种更简洁、更安全的资源管理方式,它会自动处理资源的获取和释放。

with open("test.txt", "r") as file:
    content = file.read()
    print(content)
# 无需手动调用 file.close(),with 语句会自动处理

9. 异常在模块和类中的应用

9.1 模块中的异常处理

在模块中,通常会定义一些函数供其他模块调用。在这些函数中,要合理处理可能出现的异常,并根据情况将异常抛出给调用者。

# module.py
def divide_numbers(a, b):
    if b == 0:
        raise ZeroDivisionError("除数不能为零!")
    return a / b
# main.py
import module

try:
    result = module.divide_numbers(5, 0)
except ZeroDivisionError as zde:
    print(zde)

9.2 类中的异常处理

在类的方法中,也需要进行异常处理。可以根据类的功能和使用场景,自定义异常类并在合适的时候抛出。

class BankAccount:
    def __init__(self, balance):
        if balance < 0:
            raise ValueError("账户余额不能为负数!")
        self.balance = balance

    def withdraw(self, amount):
        if amount > self.balance:
            raise ValueError("取款金额超过账户余额!")
        self.balance -= amount
        return self.balance

try:
    account = BankAccount(-10)
except ValueError as ve:
    print(ve)

try:
    valid_account = BankAccount(100)
    valid_account.withdraw(200)
except ValueError as ve:
    print(ve)

在上述代码中,BankAccount 类的初始化方法和 withdraw 方法都进行了异常处理,确保对象的状态和操作的合法性。

结语
感谢您的阅读!期待您的一键三连!欢迎指正!

在这里插入图片描述


http://www.kler.cn/a/549183.html

相关文章:

  • PHP基础部分
  • HTTP、HTTPS区别可靠性及POST为什么比GET安全的探讨
  • 光化学腐蚀法制作DIY钢网的制作流程
  • qt:对象树,窗口坐标,信号与槽
  • 【网络】协议与网络版计算器
  • BMS项目-面试及答疑整理
  • linux--关于linux文件IO(2) open、read、lseek、stat
  • C#中的动态类型用法总结带演示代码
  • 【函数题】6-12 二叉搜索树的操作集
  • AI程序员(aider)+ollama+DeepSeek-R1安装配置和使用
  • 「vue3-element-admin」Vue3 + TypeScript 项目整合 Animate.css 动画效果实战指南
  • (学习总结24)Linux 基本命令2
  • Ollama 开发指南
  • 索引----数据库
  • 30个常用的DEEPSEEK提示词
  • B+Tree在mysql中的使用
  • 前端高级面试题
  • 大语言模型简史:从Transformer(2017)到DeepSeek-R1(2025)的进化之路
  • 分布式 IO 模块:水稻加工设备的智能 “中枢”
  • Cursor 小白入门