7.2 Try Except语句


文章目录


前言

本文主要介绍异常处理基础、完整的异常处理结构、异常对象和自定义异常以及应用场景等知识点。


一、异常处理基础

1. 基本语法结构

python 复制代码
python
try:
    # 可能出错的代码
    代码块
except 异常类型:
    # 处理异常的代码
    处理代码

2. 为什么要用try-except?

python 复制代码
python
# 没有异常处理的代码会直接崩溃
print("程序开始")

# 这些代码可能会出错
number = int("abc")  # 这里会崩溃!
print(f"数字是: {number}")

print("程序结束")  # 这行永远不会执行

# 使用try-except可以让程序继续运行
print("\n=== 使用try-except ===")
print("程序开始")

try:
    number = int("abc")  # 这行会出错
    print(f"数字是: {number}")
except ValueError:
    print("错误:无法将字符串转换为整数")

print("程序正常结束")  # 这行会执行

3. 捕获特定异常

python 复制代码
python
# 示例1:处理除零错误
def divide_numbers(a, b):
    """除法运算,处理除零错误"""
    try:
        result = a / b
        return result
    except ZeroDivisionError:
        return "错误:除数不能为零"

print("除法测试:")
print(f"10 / 2 = {divide_numbers(10, 2)}")
print(f"10 / 0 = {divide_numbers(10, 0)}")

# 示例2:处理文件不存在错误
def read_file(filename):
    """读取文件,处理文件不存在的情况"""
    try:
        with open(filename, 'r', encoding='utf-8') as file:
            content = file.read()
        return content
    except FileNotFoundError:
        return f"错误:文件 '{filename}' 不存在"
    except PermissionError:
        return f"错误:没有权限读取文件 '{filename}'"

print("\n文件读取测试:")
print(read_file("存在的文件.txt"))      # 如果文件存在
print(read_file("不存在的文件.txt"))    # 文件不存在

二、完整的异常处理结构

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

python 复制代码
python
def process_data(data_str):
    """
    完整的异常处理示例
    try-except-else-finally结构
    """
    result = None
    
    try:
        print("尝试处理数据...")
        # 可能出错的代码
        number = float(data_str)
        result = number * 2
        
    except ValueError:
        print(f"错误:'{data_str}' 不是有效的数字")
        
    except TypeError:
        print("错误:输入类型不正确")
        
    else:
        # 只有当try块没有异常时才执行
        print(f"处理成功!原始数据: {data_str}, 结果: {result}")
        
    finally:
        # 无论是否发生异常都会执行
        print("清理资源...")
        print("-" * 40)
    
    return result

# 测试各种情况
print("测试1:正常数据")
process_data("10.5")

print("测试2:无效数据")
process_data("abc")

print("测试3:None值")
process_data(None)

# finally的典型应用场景
def read_config_file(filename):
    """读取配置文件,确保文件被关闭"""
    file = None
    try:
        file = open(filename, 'r', encoding='utf-8')
        content = file.read()
        config = eval(content)  # 危险!仅作示例
        return config
    except FileNotFoundError:
        print(f"配置文件 {filename} 不存在")
        return {}
    except SyntaxError:
        print(f"配置文件 {filename} 格式错误")
        return {}
    finally:
        # 确保文件总是被关闭
        if file and not file.closed:
            file.close()
            print(f"已关闭文件: {filename}")

2. 捕获多个异常

python 复制代码
python
# 方法1:多个except块
def handle_multiple_errors_1(data):
    """多个except块处理不同异常"""
    try:
        # 多种可能的错误
        index = int(data)
        numbers = [10, 20, 30, 40, 50]
        result = numbers[index] / (index - 2)  # 可能除零
        
        return f"结果: {result}"
        
    except ValueError:
        return "错误:请输入有效的整数"
        
    except IndexError:
        return "错误:索引超出范围,有效索引是0-4"
        
    except ZeroDivisionError:
        return "错误:除数不能为零(索引不能为2)"
        
    except Exception as e:
        # 捕获其他所有异常
        return f"未知错误: {type(e).__name__}: {e}"

# 测试
test_cases = ["abc", "10", "2", "3", "0"]
for test in test_cases:
    print(f"输入 '{test}': {handle_multiple_errors_1(test)}")

# 方法2:一个except块捕获多个异常
def handle_multiple_errors_2(data):
    """一个except块捕获多个异常"""
    try:
        index = int(data)
        numbers = [10, 20, 30, 40, 50]
        result = numbers[index] / (index - 2)
        
        return f"结果: {result}"
        
    except (ValueError, IndexError, ZeroDivisionError) as e:
        # 处理多种异常
        error_type = type(e).__name__
        
        if error_type == "ValueError":
            return "错误:请输入有效的整数"
        elif error_type == "IndexError":
            return "错误:索引超出范围"
        elif error_type == "ZeroDivisionError":
            return "错误:除数不能为零"
            
    except Exception as e:
        return f"其他错误: {e}"

print("\n" + "="*40 + "\n")
for test in test_cases:
    print(f"输入 '{test}': {handle_multiple_errors_2(test)}")

三、异常对象和自定义异常

1. 获取异常信息

python 复制代码
python
def analyze_error(data):
    """分析异常信息"""
    try:
        result = 100 / int(data)
        return f"成功: {result}"
        
    except Exception as e:
        # 获取异常的详细信息
        print(f"异常类型: {type(e).__name__}")
        print(f"异常信息: {e}")
        print(f"异常参数: {e.args}")
        
        # 获取更多调试信息
        import traceback
        print("\n异常追踪:")
        traceback.print_exc()
        
        return f"失败: {type(e).__name__}"

print("分析错误信息:")
print(analyze_error("0"))
print("\n" + "="*40)
print(analyze_error("abc"))

2. 自定义异常

python 复制代码
python
# 创建自定义异常类
class ValidationError(Exception):
    """自定义验证错误"""
    def __init__(self, message, field=None):
        super().__init__(message)
        self.field = field
        self.message = message
    
    def __str__(self):
        if self.field:
            return f"{self.field}字段验证失败: {self.message}"
        return f"验证失败: {self.message}"

class InsufficientBalanceError(Exception):
    """余额不足错误"""
    def __init__(self, balance, amount):
        super().__init__(f"余额不足: 当前余额{balance},需要{amount}")
        self.balance = balance
        self.amount = amount

# 使用自定义异常
def validate_user_input(username, password):
    """验证用户输入"""
    if not username or not username.strip():
        raise ValidationError("用户名不能为空", field="username")
    
    if len(password) < 6:
        raise ValidationError("密码长度至少6位", field="password")
    
    if not any(c.isdigit() for c in password):
        raise ValidationError("密码必须包含数字", field="password")
    
    print("验证通过!")
    return True

def withdraw_money(balance, amount):
    """取款操作"""
    if amount <= 0:
        raise ValueError("取款金额必须大于0")
    
    if amount > balance:
        raise InsufficientBalanceError(balance, amount)
    
    balance -= amount
    print(f"取款成功!剩余余额: {balance}")
    return balance

# 测试自定义异常
print("测试1:用户验证")
try:
    validate_user_input("", "123")
except ValidationError as e:
    print(f"捕获到验证错误: {e}")
    print(f"错误字段: {e.field}")

print("\n测试2:取款操作")
try:
    withdraw_money(1000, 1500)
except InsufficientBalanceError as e:
    print(f"捕获到余额不足错误: {e}")
    print(f"当前余额: {e.balance}, 需要金额: {e.amount}")
except ValueError as e:
    print(f"捕获到值错误: {e}")

print("\n测试3:链式异常处理")
try:
    try:
        validate_user_input("admin", "123")
    except ValidationError as e:
        print(f"内层捕获: {e}")
        # 可以重新抛出异常
        raise  # 重新抛出当前异常
except ValidationError as e:
    print(f"外层捕获: {e}")

3. 异常链

python 复制代码
python
def process_data_file(filename):
    """处理数据文件,演示异常链"""
    try:
        with open(filename, 'r') as file:
            data = file.read()
            numbers = [int(x) for x in data.split()]
            average = sum(numbers) / len(numbers)
            return average
            
    except FileNotFoundError as e:
        # 添加更多上下文信息
        raise FileNotFoundError(f"无法处理文件 '{filename}'") from e
        
    except ValueError as e:
        # 转换异常类型
        raise RuntimeError(f"文件 '{filename}' 包含无效数据") from e

# 测试异常链
try:
    result = process_data_file("nonexistent.txt")
except Exception as e:
    print(f"主错误: {e}")
    print(f"原因: {e.__cause__}")
    
    # 显示完整的异常链
    import traceback
    print("\n完整异常链:")
    traceback.print_exc()

四、实际应用场景

1. 用户输入验证

python 复制代码
python
def get_valid_number(prompt, min_value=None, max_value=None):
    """获取有效的数字输入"""
    while True:
        try:
            user_input = input(prompt)
            number = float(user_input)
            
            # 验证范围
            if min_value is not None and number < min_value:
                raise ValueError(f"数字不能小于 {min_value}")
            
            if max_value is not None and number > max_value:
                raise ValueError(f"数字不能大于 {max_value}")
            
            return number
            
        except ValueError as e:
            if "could not convert" in str(e):
                print(f"错误: '{user_input}' 不是有效的数字")
            else:
                print(f"错误: {e}")
            print("请重新输入...\n")

# 使用
print("用户输入验证示例:")
age = get_valid_number("请输入年龄(0-150): ", min_value=0, max_value=150)
temperature = get_valid_number("请输入温度(-50 to 60): ", min_value=-50, max_value=60)

print(f"年龄: {age:.0f}岁")
print(f"温度: {temperature:.1f}°C")

相关推荐
额呃呃2 小时前
select和poll之间的性能对比
开发语言·算法
星轨初途2 小时前
C++ string 类详解:概念、常用操作与实践(算法竞赛类)
开发语言·c++·经验分享·笔记·算法
二进制_博客2 小时前
JWT权限认证快速入门
java·开发语言·jwt
程序员佳佳2 小时前
026年AI开发实战:从GPT-5.2到Gemini-3,如何构建下一代企业级Agent架构?
开发语言·python·gpt·重构·api·ai写作·agi
橙露2 小时前
Python 图形任意角度旋转完整解决方案:原理、实现与可视化展示
开发语言·python
大模型铲屎官2 小时前
【操作系统-Day 46】文件系统核心探秘:深入理解连续分配与链式分配的实现与优劣
人工智能·python·深度学习·大模型·操作系统·文件系统·计算机组成原理
csbysj20202 小时前
Perl 数组
开发语言
雾岛听蓝2 小时前
C++ vector:从使用到底层核心剖析
开发语言·c++