文章目录

Python 异常处理:捕获与处理常见异常

发布于 2026-04-02 12:45:13 · 浏览 9 次 · 评论 0 条

Python 异常处理:捕获与处理常见异常

Python 程序在运行过程中可能因各种原因出错,比如文件不存在、用户输入了无效数据、网络连接失败等。这些错误被称为“异常”。如果不处理,程序会直接崩溃。使用 try...except 语句可以捕获异常并优雅地处理它们,避免程序意外终止


基础异常处理结构

  1. 编写 try:将可能出错的代码放在 try 后面。
  2. 编写 except:指定要捕获的异常类型,并定义应对措施。
  3. 可选添加 else:仅当 try 中没有异常时才执行。
  4. 可选添加 finally:无论是否发生异常都会执行,常用于清理资源(如关闭文件)。
try:
    # 可能出错的代码
    result = 10 / 0
except ZeroDivisionError:
    # 处理除零错误
    print("不能除以零!")
else:
    # 没有异常时执行
    print(f"结果是: {result}")
finally:
    # 总是执行
    print("计算完成。")

运行上述代码,输出为:

不能除以零!
计算完成。

捕获多种常见异常

实际开发中,一段代码可能触发多种不同类型的异常。使用多个 except 子句可以分别处理不同错误

try:
    num = int(input("请输入一个整数: "))
    result = 100 / num
    print(f"100 除以 {num} 等于 {result}")
except ValueError:
    print("输入的不是有效整数!")
except ZeroDivisionError:
    print("不能除以零!")
except Exception as e:
    print(f"发生了未预期的错误: {e}")
  • 如果用户输入 "abc",会触发 ValueError
  • 如果输入 0,会触发 ZeroDivisionError
  • 其他未预料的错误由通用的 Exception 捕获。

注意except Exception 应放在所有具体异常之后,否则会“吞掉”本应单独处理的错误。


查看常见内置异常类型

Python 提供了丰富的内置异常类。以下是几个最常用的:

异常名称 触发场景 示例
ValueError 函数接收到正确类型但值不合法 int("hello")
TypeError 对不支持的操作传入了错误类型 "a" + 5
IndexError 列表或元组索引超出范围 [1,2][5]
KeyError 字典中找不到指定键 {"a":1}["b"]
FileNotFoundError 尝试打开不存在的文件 open("no_such.txt")
ZeroDivisionError 除法或取模运算中除数为零 10 / 0

主动抛出异常

有时你需要在特定条件下中断程序流程。使用 raise 关键字可以手动抛出异常

def divide(a, b):
    if b == 0:
        raise ValueError("除数不能为零")
    return a / b

try:
    result = divide(10, 0)
except ValueError as e:
    print(f"错误: {e}")

输出:

错误: 除数不能为零

你也可以抛出内置异常的子类,或自定义异常类(见下文)。


自定义异常类

当内置异常无法准确描述你的业务错误时,创建自己的异常类能让代码更清晰

  1. 继承 Exception
  2. 通常只需定义 __init__ 方法和错误信息
class InvalidAgeError(Exception):
    def __init__(self, age):
        self.age = age
        super().__init__(f"年龄 {age} 不合法,必须在 0 到 150 之间")

def set_age(age):
    if age < 0 or age > 150:
        raise InvalidAgeError(age)
    print(f"年龄设置为: {age}")

try:
    set_age(-5)
except InvalidAgeError as e:
    print(e)

输出:

年龄 -5 不合法,必须在 0 到 150 之间

安全读取文件的最佳实践

文件操作极易引发异常(如文件不存在、权限不足)。结合 try...exceptwith 语句可确保资源安全释放

filename = "data.txt"
try:
    with open(filename, 'r', encoding='utf-8') as f:
        content = f.read()
        print(content)
except FileNotFoundError:
    print(f"文件 {filename} 不存在")
except PermissionError:
    print(f"没有权限读取文件 {filename}")
except UnicodeDecodeError:
    print(f"文件 {filename} 编码格式不支持")
  • with open(...) 确保文件在使用后自动关闭,即使发生异常。
  • 分别捕获 FileNotFoundErrorPermissionError 等具体错误,提供明确提示。

避免空的 except 块

永远不要写裸露的 except:,因为它会捕获包括系统退出(KeyboardInterruptSystemExit)在内的所有异常,导致程序无法正常终止。

❌ 错误示例:

try:
    risky_operation()
except:  # 危险!会隐藏所有错误
    pass

✅ 正确做法:

try:
    risky_operation()
except SpecificError:
    handle_error()

如果确实需要捕获所有非系统异常,使用 except Exception:


记录异常日志

在生产环境中,将异常信息写入日志比直接打印到控制台更有用

import logging

logging.basicConfig(level=logging.ERROR)

try:
    value = int("not_a_number")
except ValueError as e:
    logging.error("转换失败", exc_info=True)

exc_info=True 会记录完整的异常堆栈,便于调试。


异常链:保留原始错误信息

当你在处理一个异常时又引发了新异常,使用 raise ... from ... 可以保留原始错误上下文

def process_data(data):
    try:
        return int(data)
    except ValueError as e:
        raise RuntimeError("数据处理失败") from e

try:
    process_data("xyz")
except RuntimeError as e:
    print(f"新异常: {e}")
    print(f"原始异常: {e.__cause__}")

输出显示新旧两个异常,帮助追踪问题根源。


不要过度使用异常控制流程

异常机制不应替代常规逻辑判断。频繁使用异常会影响性能,且降低代码可读性

❌ 不推荐:

try:
    value = my_dict["key"]
except KeyError:
    value = "default"

✅ 推荐:

value = my_dict.get("key", "default")

仅在真正“异常”的情况下使用异常处理,而非作为常规分支手段。

评论 (0)

暂无评论,快来抢沙发吧!

扫一扫,手机查看

扫描上方二维码,在手机上查看本文