Python异常处理代码写法:try-except的正确使用

沿途有光
沿途有光
发布时间:2026-10-23| 7人浏览过
原创

在编写 Python 应用程序时,文件读写失败、网络连接中断或键名不存在等运行时意外不可避免。异常处理的核心目的不是掩盖程序中存在的逻辑错误,而是在可预期的意外发生时,提供受控的恢复路径或清晰的错误记录。本文直接梳理 try-except 语法体系的标准代码写法、完整的四段式控制流程、精确捕获与链式抛出的实现方式,以及工程排查中必须遵循的防坑规范。

一、基础骨架与完整执行顺序

Python 的异常处理结构不仅包含 try 和 except,还支持配合 else 与 finally 形成完整的四段式防护体系。明确这四个关键词的执行次序,是写出可靠防错逻辑的前提:

  • try 块:存放可能引发异常的目标操作。原则上只包裹可能出错的关键行,不放无关代码。
  • except 块:当 try 块内部抛出匹配的异常时触发,执行降级恢复、告警或备用逻辑。
  • else 块:当 try 块没有抛出任何异常并顺利执行结束时触发。常用于执行依赖前序操作成功才能进行的下游业务。
  • finally 块:无论 try 块是否发生异常、无论 except 块是否捕获成功,该代码块必定会执行,主要用于无条件清理文件句柄、数据库连接或释放线程锁。
Python异常处理代码写法:try-except的正确使用
图 1:Python try-except-else-finally 完整控制流转步骤

下面通过一个处理用户输入并解析整数的具体示例,展示四段式语句的标准代码结构:

def parse_user_age(raw_text):
    try:
      # 1. 尝试执行可能失败的数据解析
      age = int(raw_text)
    except ValueError as err:
      # 2A. 捕获格式错误并给出保底反馈
      print(f"解析失败,输入内容非法: {err}")
      return None
    else:
      # 2B. 仅在解析成功时才执行业务校验
      print(f"数据解析成功,登记年龄为: {age}")
      return age
    finally:
      # 3. 无论成功与否均执行收尾记录
      print("本次 parse_user_age 调用执行完毕\n")
示例执行结果展示:
调用 parse_user_age("28") 输出:
数据解析成功,登记年龄为: 28
本次 parse_user_age 调用执行完毕
调用 parse_user_age("abc") 输出:
解析失败,输入内容非法: invalid literal for int() with base 10: 'abc'
本次 parse_user_age 调用执行完毕

二、精准捕获原则:拒绝裸 except 与宽泛拦截

新手编写异常处理时最常犯的错误是直接书写 except:(裸捕获)或者无节制地使用 except Exception:。这种写法会将语法错误(如变量名拼错导致的 NameError)、程序退出中断信号(如终端按下的 Ctrl+C KeyboardInterrupt)以及真正的业务异常全部静默拦截,给调试带来灾难。

编写生产环境代码时必须遵循“捕获具体异常类型”的原则。如果一段代码可能抛出多种不同的可预期异常,应当根据不同的异常类型分别处理,或者使用元组进行组合拦截。

Python异常处理代码写法:try-except的正确使用
图 2:泛化盲目捕获与精准声明捕获的代码实践对比

多异常分别处理与合并捕获的标准写法

当不同的错误需要执行不同的补救动作时,使用多个连续的 except 块进行区分处理。如果多种错误的处理策略完全一致,则使用小括号将异常类封装为元组:

def safe_read_configuration(config_dict, key, default_val=None):
    try:
      # 可能发生键不存在 (KeyError),或者参数类型不合法 (TypeError)
      raw_val = config_dict[key]
      result = int(raw_val)
      return result
    except KeyError:
      # 针对缺少配置项的情况单独降级
      print(f"未找到配置项 [{key}],启用默认值: {default_val}")
      return default_val
    except (ValueError, TypeError) as err:
      # 针对类型或数值转换问题统一记录
      print(f"配置项 [{key}] 格式无效,具体原因: {err}")
      return default_val

三、获取异常对象与上下文重抛(raise 与 raise from)

捕获异常后,常常需要将底层具体异常封装为高阶的业务异常,或者仅仅打印日志后原样向上传播,避免破坏原有的调用栈。

Python异常处理代码写法:try-except的正确使用
图 3:Python 核心异常继承体系与 raise ... from 链式追溯机制

1. 原样重新抛出 (裸 raise)

在当前函数中执行完日志记录或警报后,如果希望调用方感知该异常并做进一步处理,应当使用单独的 raise 语句。注意不要写成 raise err,直接使用 raise 可以完整保留最原始的堆栈行号信息:

import logging

def execute_remote_call(url):
    try:
      response = requests.get(url, timeout=5)
      response.raise_for_status()
      return response.json()
    except requests.RequestException as err:
      # 记录本地日志后直接重新抛出原始异常
      logging.error("网络请求发生故障,正在向上传递: %s", err)
      raise  # 保留原始 traceback 调用栈

2. 异常链包装 (raise ... from)

在对外暴露公共接口或 SDK 时,通常不希望直接泄露底层的实现细节(例如直接抛出 sqlite3.OperationalError),而是将其转化为领域专属的业务异常(例如 UserNotFoundError)。使用 from 语法可以把两段异常串联起来:

class DatabaseRecordError(Exception):
    """自定义业务数据访问异常"""
    pass

def load_user_profile(user_id):
    try:
      with open(f"/var/data/users/{user_id}.json", "r", encoding="utf-8") as f:
        return json.load(f)
    except FileNotFoundError as err:
      # 向上抛出业务异常,同时将 err 挂载到新异常的 __cause__ 属性中
      raise DatabaseRecordError(f"目标用户档案不存在: {user_id}") from err

四、资源清理:finally 与上下文管理器 with 的选择

当涉及外部资源(网络连接、临时文件、线程互斥锁)时,必须确保无论中间逻辑是否抛出异常,资源都能被安全归还。

工程规范建议:在现代 Python 代码中,处理文件、网络会话或线程锁时,首选 with 上下文管理器;仅当无法使用上下文协议、或需要结合多步条件分支做自定义状态重置时,才使用 finally 结构。

使用 try-finally 的标准写法如下:

def process_data_with_cleanup():
    resource = allocate_heavy_resource()
    try:
      resource.do_work()
    finally:
      # 无论 do_work 是否成功,确保释放资源
      resource.release()

而如果被操作的对象实现了上下文协议(__enter__ 和 __exit__),使用 with 语句可大幅精简代码并提升可读性:

# 推荐的简洁写法:利用 with 自动处理隐式 try-finally 逻辑
def read_log_file(filepath):
    try:
      with open(filepath, "r", encoding="utf-8") as file:
        return file.readlines()
    except FileNotFoundError:
      return []

五、生产环境 try-except 四维自查规范

为了保证异常处理代码在大型项目与协同开发中保持高质量,推荐在编码自查时对照以下四条核心维度:

Python异常处理代码写法:try-except的正确使用
图 4:Python 异常处理工程规范与避坑自查四维清单

六、总结

正确使用 try-except 并不是简单地给可能报错的语句套上一层安全壳,而是建立一套对异常有预期、有分类、可定位、有收尾的容错流转体系:

  1. 用 try 包裹单步风险,用 else 承接成功逻辑,用 finally 托底收尾动作;
  2. 始终捕获具体异常类,绝不使用裸 except: 或无条件 pass;
  3. 善用 raise 原样抛出保持原始调用栈,或使用 raise ... from 维护清晰的异常上下文链;
  4. 对于常规 I/O 与连接资源,优先借助 with 上下文管理器实现自动清理。

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。