Python学习笔记:错误和异常处理

1. 什么是错误和异常

在Python中,错误可以分为两类:

  • 语法错误(Syntax Errors):代码不符合Python语法规则
  • 异常(Exceptions):语法正确的代码在运行时发生的错误
python 复制代码
# 语法错误示例
print("Hello World"  # 缺少右括号

# 异常示例
print(10 / 0)  # ZeroDivisionError: division by zero

2. 常见的异常类型

Python内置了许多异常类型,常见的有:

python 复制代码
# NameError - 尝试访问未定义的变量
print(undefined_variable)

# TypeError - 类型操作错误
"2" + 2  # 不能将字符串和整数相加

# IndexError - 索引超出范围
lst = [1, 2, 3]
print(lst[3](@ref)

# KeyError - 字典键不存在
d = {'a': 1}
print(d['b'])

# FileNotFoundError - 文件不存在
open('nonexistent.txt')

3. 异常处理:try-except语句

使用try-except可以捕获并处理异常:

python 复制代码
try:
    # 可能引发异常的代码
    result = 10 / 0
except ZeroDivisionError:
    # 处理特定异常
    print("不能除以零!")

捕获多种异常

python 复制代码
try:
    num = int(input("请输入一个数字: "))
    result = 100 / num
    print("结果是:", result)
except ValueError:
    print("输入的不是有效数字!")
except ZeroDivisionError:
    print("不能输入零!")
except Exception as e:  # 捕获所有其他异常
    print(f"发生未知错误: {e}")

4. try-except-else-finally完整结构

python 复制代码
try:
    file = open('example.txt', 'r')
    content = file.read()
except FileNotFoundError:
    print("文件不存在!")
else:
    # 如果没有异常发生,执行else块
    print("文件内容:", content)
finally:
    # 无论是否发生异常都会执行
    print("清理工作...")
    if 'file' in locals() and not file.closed:
        file.close()

5. 抛出异常:raise语句

我们可以主动抛出异常:

python 复制代码
def check_age(age):
    if age < 0:
        raise ValueError("年龄不能为负数")
    elif age < 18:
        raise ValueError("未成年禁止访问")
    else:
        print("欢迎访问")

try:
    check_age(-5)
except ValueError as e:
    print(f"错误: {e}")

6. 自定义异常

我们可以创建自己的异常类型:

python 复制代码
class MyCustomError(Exception):
    """自定义异常类 - 用于演示特定业务场景的错误"""
    def __init__(self, message, error_code=500):
        self.message = message
        self.error_code = error_code
        super().__init__(f"错误代码 {error_code}: {message}")

    def __str__(self):
        """自定义异常信息的字符串表示形式"""
        return f"[{self.__class__.__name__}] {self.message}"


def calculate_division(dividend, divisor):
    """演示函数:执行除法运算,当条件不满足时抛出不同类型的异常"""
    if not isinstance(dividend, (int, float)) or not isinstance(divisor, (int, float)):
        raise TypeError("被除数和除数必须是数字类型")
    
    if divisor == 0:
        raise ZeroDivisionError("除数不能为零")
    
    if dividend < 0 or divisor < 0:
        # 抛出自定义异常:当输入为负数时
        raise MyCustomError("计算不支持负数输入", error_code=400)
    
    return dividend / divisor


def main():
    """主函数:演示异常的捕获和处理流程"""
    print("=== 自定义异常演示程序 ===")
    
    while True:
        try:
            # 获取用户输入
            num1 = float(input("\n请输入被除数(输入q退出):"))
            num2 = float(input("请输入除数:"))
            
            # 执行计算
            result = calculate_division(num1, num2)
            print(f"计算结果:{num1} ÷ {num2} = {result}")
        
        except ValueError as e:
            # 处理非数字输入
            if "q" in str(e).lower():
                print("程序已退出")
                break
            print(f"输入错误:请输入有效的数字。错误详情:{e}")
        
        except ZeroDivisionError as e:
            # 处理内置异常
            print(f"数学错误:{e}")
        
        except MyCustomError as e:
            # 处理自定义异常
            print(f"业务错误:{e}(错误代码:{e.error_code})")
        
        except TypeError as e:
            # 处理类型错误
            print(f"类型错误:{e}")
        
        except Exception as e:
            # 捕获所有其他未预期的异常
            print(f"未知错误:{e}")
            break


if __name__ == "__main__":
    main()    

这个示例程序包含以下关键特性:

  1. 自定义异常类MyCustomError继承自Exception,包含错误信息和错误代码
  2. 异常抛出函数calculate_division根据不同条件抛出不同类型的异常
  3. 多级异常捕获 :在main函数中使用多个except块分别处理不同类型的异常
  4. 用户交互:通过控制台输入演示异常的触发和处理流程
    你可以运行这段代码并尝试以下输入场景:
  • 正常输入两个正数(如102
  • 输入零作为除数(触发ZeroDivisionError
  • 输入负数(触发MyCustomError
  • 输入非数字字符(触发ValueError
  • 输入q退出程序

通过观察不同输入下的输出结果,你可以深入理解自定义异常的工作机制和优势。

7. 断言assert

assert用于确保某个条件为真,否则抛出AssertionError:

python 复制代码
def divide(a, b):
    assert b != 0, "除数不能为零"
    return a / b

print(divide(10, 2))  # 正常
print(divide(10, 0))  # 抛出AssertionError

8. 实际应用案例

案例1:处理用户输入

python 复制代码
while True:
    try:
        age = int(input("请输入您的年龄: "))
        if age < 0:
            raise ValueError("年龄不能为负数")
        break
    except ValueError as e:
        print(f"无效输入: {e}")

print(f"您的年龄是: {age}")

案例2:文件操作

python 复制代码
def read_file(filename):
    try:
        with open(filename, 'r') as file:
            return file.read()
    except FileNotFoundError:
        print(f"文件 {filename} 不存在")
        return None
    except IOError:
        print(f"读取文件 {filename} 时发生错误")
        return None

content = read_file('data.txt')
if content:
    print("文件内容:", content)

案例3:网络请求

python 复制代码
import requests

def fetch_url(url):
    try:
        response = requests.get(url, timeout=5)
        response.raise_for_status()  # 如果请求不成功,抛出HTTPError
        return response.text
    except requests.exceptions.Timeout:
        print("请求超时")
    except requests.exceptions.HTTPError as err:
        print(f"HTTP错误: {err}")
    except requests.exceptions.RequestException as err:
        print(f"请求错误: {err}")
    return None

html = fetch_url("https://www.example.com")
if html:
    print("获取内容成功!")

9. 异常处理的最佳实践

  1. 1.不要过度使用try-except:只捕获你知道如何处理的异常
  2. 2.尽量具体:捕获特定异常而不是通用的Exception
  3. 3.记录异常信息:使用logging模块记录异常详情
  4. 4.保持简洁:try块中只包含可能引发异常的代码
  5. 5.清理资源:使用finally或上下文管理器(with语句)确保资源释放
python 复制代码
import logging

logging.basicConfig(filename='app.log', level=logging.ERROR)

def process_data(data):
    try:
        # 只包含可能引发异常的代码
        result = complex_operation(data)
    except ValueError as e:
        logging.error(f"处理数据时发生值错误: {e}")
        return None
    except DatabaseError as e:
        logging.error(f"数据库错误: {e}")
        return None
    else:
        return result

10. 总结

异常处理是Python编程中非常重要的部分,合理使用异常处理可以使程序:

  • 更加健壮,能够处理意外情况
  • 更易于调试和维护
  • 提供更好的用户体验

异常处理不是用来隐藏错误的,而是为了优雅地处理错误情况!

相关推荐
固定资产管理系统软件8 分钟前
商务局RFID固定资产管理系统的应用价值与落地要点解析
大数据·python
码农颜29 分钟前
6.3 主函数流程剖析
开发语言·php
tju新生代魔迷34 分钟前
Python学习日记3
学习
研☆香1 小时前
聊一聊前端的常见字 关键字
开发语言·前端·javascript
lancyu1 小时前
关于多轮对话机器人的上下文Token优化和解决方案
人工智能·python·深度学习·机器学习·chatgpt·机器人·prompt
草莓橙子碗2 小时前
Claude 使用指南
开发语言·python
hsjiasb2 小时前
FreeRTOS学习(三十九)——最终总结
学习·学习笔记·freertos
工具分享2 小时前
陪跑跟品爆单AI选品助手,高效跟品会赔本吗?
人工智能·python
COOLMO研究AI2 小时前
Python 如何实现 AI API 的提示词(Prompt)版本管理与热更新
人工智能·python·prompt
老郑聊AI业财智造2 小时前
Transformer 技术架构与源码分析
人工智能·python·深度学习·语言模型·架构·transformer·软件工程