个人主页:Guiat
归属专栏:Python
正文
1. 错误和异常的概念
1.1 错误
在 Python 里,错误一般可分为语法错误和逻辑错误。
- 语法错误:是指代码编写不符合 Python 语法规则,导致 Python 表明器无法正确解析代码。例如,少了冒号、括号不匹配等。
- # 语法错误示例,if 语句后缺少冒号
- if True
- print("This is a syntax error.")
复制代码
- 逻辑错误:代码语法上没有问题,但程序运行结果不符合预期。这通常是由于算法设计错误、变量使用不当等缘故原由造成的。例如,在计算匀称值时,分母大概为 0。
1.2 异常
异常是在程序运行过程中出现的错误事件,它会打断程序的正常执行流程。Python 有许多内置异常范例,如 ZeroDivisionError、IndexError 等。
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 方法都进行了异常处置惩罚,确保对象的状态和操作的正当性。
结语
感谢您的阅读!期待您的一键三连!欢迎指正!
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |