初面网初面网

错误处理——try / except / finally

概念讲解

程序运行中难免出错:用户输入错误、网络断开、文件不存在……错误处理让程序在出错时不是崩溃,而是优雅地应对。

try:
    # 尝试执行这段代码
    risky_operation()
except 错误类型 as e:
    # 如果出错,执行这里
    handle_error(e)
else:
    # 如果没出错,执行这里(可选)
    success_path()
finally:
    # 无论是否出错,都执行这里(可选)
    cleanup()

常见错误类型:

  • ValueError:值不合法
  • TypeError:类型不匹配
  • FileNotFoundError:文件不存在
  • KeyError:字典的key不存在
  • IndexError:列表索引越界

原则:

  • 只捕获你预期会发生的错误
  • 捕获后要处理,不要吞掉(空 except 是坏习惯)
  • 必要时重新抛出异常(raise

代码示例

读取并解析配置文件

def parse_config(file_path):
    """读取配置文件,返回字典"""
    config = {}
    try:
        with open(file_path, 'r', encoding='utf-8') as f:
            for line_num, line in enumerate(f, 1):
                line = line.strip()
                if not line or line.startswith('#'):
                    continue  # 跳过空行和注释
                if '=' not in line:
                    print(f"警告:第{line_num}行格式错误,已跳过")
                    continue
                key, value = line.split('=', 1)
                config[key.strip()] = value.strip()
    except FileNotFoundError:
        print(f"配置文件不存在: {file_path},使用默认配置")
        return {}
    except PermissionError:
        print(f"没有读取权限: {file_path}")
        return {}
    finally:
        print("配置文件读取完毕")
    return config

# 示例配置
# database = localhost
# port = 3306
# timeout = 30

result = parse_config('config.txt')
print(result)

安全的类型转换

def safe_int(value, default=0):
    """尝试将值转换为整数,失败时返回默认值"""
    try:
        return int(value)
    except (ValueError, TypeError):
        return default

# 批量转换用户输入
user_inputs = ["42", "3.14", "hello", "", "100"]
numbers = [safe_int(x) for x in user_inputs]
print(numbers)  # [42, 3, 0, 0, 100]

自定义异常

class ValidationError(Exception):
    """数据验证失败异常"""
    pass

def validate_age(age):
    if not isinstance(age, (int, float)):
        raise ValidationError(f"年龄必须是数字,得到: {type(age).__name__}")
    if age < 0 or age > 150:
        raise ValidationError(f"年龄超出正常范围: {age}")
    return int(age)

try:
    age = validate_age("twenty")
except ValidationError as e:
    print(f"验证失败: {e}")  # 验证失败: 年龄必须是数字,得到: str

练习题

题目:写一个函数 divide_if_possible(a, b),返回 a除以b的结果。

要求:

  • 如果 b 为 0,返回 None 并打印"除数不能为零"
  • 如果 a 或 b 不是数字,返回 None 并打印"参数类型错误"
  • 如果除法结果不是整数,返回浮点数(但小数部分不能超过0.0001)
参考答案
def divide_if_possible(a, b):
    try:
        if not isinstance(a, (int, float)) or not isinstance(b, (int, float)):
            print("参数类型错误")
            return None
        if b == 0:
            print("除数不能为零")
            return None
        result = a / b
        # 检查小数部分
        fractional = result - int(result)
        if result != int(result) and fractional > 0.0001:
            return result
        return int(result)
    except Exception as e:
        # 捕获其他未知错误(如NaN、无穷大)
        print(f"未知错误: {e}")
        return None

print(divide_if_possible(10, 3))      # 3.333... 返回
print(divide_if_possible(10, 2))      # 5
print(divide_if_possible(10, 0))      # 除数不能为零 None
print(divide_if_possible("a", 2))     # 参数类型错误 None

关键思维:

  • try/except 的粒度要合适,不要用空 except
  • isinstance 检查比 type() == 更准确(考虑继承)
  • else 分流成功路径也是一个好习惯

更新于 2026/6/7