程序员scholar 程序员scholar
首页
  • Java 基础

    • JavaSE
    • JavaIO
    • JavaAPI速查
  • Java 高级

    • JUC
    • JVM
    • Java新特性
    • 设计模式
  • Web 开发

    • Servlet
    • Java网络编程
  • 数据结构
  • HTTP协议
  • HTTPS协议
  • 计算机网络
  • Linux常用命令
  • Windows常用命令
  • SQL数据库

    • MySQL
    • MySQL速查
  • NoSQL数据库

    • Redis
    • ElasticSearch
  • 数据库

    • MyBatis
    • MyBatis-Plus
  • 消息中间件

    • RabbitMQ
  • 服务器

    • Nginx
  • Python 基础

    • Python基础
  • Python 进阶

    • 装饰器与生成器
    • 异常处理
    • 标准库精讲
    • 模块与包
    • pip包管理工具
  • Spring框架

    • Spring6
    • SpringMVC
    • SpringBoot
    • SpringSecurity
  • SpringCould微服务

    • SpringCloud基础
    • 微服务之DDD架构思想
  • 日常必备

    • 开发常用工具包
    • Hutoll工具包
    • IDEA常用配置
    • 开发笔记
    • 日常记录
    • 项目部署
    • 网站导航
    • 产品学习
    • 英语学习
  • 代码管理

    • Maven
    • Git教程
    • Git小乌龟教程
  • 运维工具

    • Docker
    • Jenkins
    • Kubernetes
前端 (opens new window)
  • 算法笔记

    • 算法思想
    • 刷题笔记
  • 面试问题常见

    • 十大经典排序算法
    • 面试常见问题集锦
关于
GitHub (opens new window)
首页
  • Java 基础

    • JavaSE
    • JavaIO
    • JavaAPI速查
  • Java 高级

    • JUC
    • JVM
    • Java新特性
    • 设计模式
  • Web 开发

    • Servlet
    • Java网络编程
  • 数据结构
  • HTTP协议
  • HTTPS协议
  • 计算机网络
  • Linux常用命令
  • Windows常用命令
  • SQL数据库

    • MySQL
    • MySQL速查
  • NoSQL数据库

    • Redis
    • ElasticSearch
  • 数据库

    • MyBatis
    • MyBatis-Plus
  • 消息中间件

    • RabbitMQ
  • 服务器

    • Nginx
  • Python 基础

    • Python基础
  • Python 进阶

    • 装饰器与生成器
    • 异常处理
    • 标准库精讲
    • 模块与包
    • pip包管理工具
  • Spring框架

    • Spring6
    • SpringMVC
    • SpringBoot
    • SpringSecurity
  • SpringCould微服务

    • SpringCloud基础
    • 微服务之DDD架构思想
  • 日常必备

    • 开发常用工具包
    • Hutoll工具包
    • IDEA常用配置
    • 开发笔记
    • 日常记录
    • 项目部署
    • 网站导航
    • 产品学习
    • 英语学习
  • 代码管理

    • Maven
    • Git教程
    • Git小乌龟教程
  • 运维工具

    • Docker
    • Jenkins
    • Kubernetes
前端 (opens new window)
  • 算法笔记

    • 算法思想
    • 刷题笔记
  • 面试问题常见

    • 十大经典排序算法
    • 面试常见问题集锦
关于
GitHub (opens new window)
npm

(进入注册为作者充电)

  • Python 基础

  • Python 进阶

    • 装饰器与生成器
    • 异常处理
      • 1. 什么是异常?
      • 2. try...except:捕获异常
        • 2.1 捕获特定异常
        • 2.2 一次捕获多种异常
        • 2.3 获取异常对象
      • 3. try...except...else 结构
      • 4. try...finally:确保执行清理
      • 5. raise:主动抛出异常
      • 6. 自定义异常
      • 7. 常见内置异常
      • 8. 异常处理最佳实践
    • 标准库精讲
    • 模块与包
    • pip 包管理工具
  • Python
  • Python 进阶
scholar
2025-07-23
目录

异常处理

# Python 异常处理

在任何编程语言中,错误都是不可避免的。一个健壮的程序不仅要能正确执行任务,还应该能够优雅地处理各种预料之外的错误。在 Python 中,这种错误处理机制就是异常处理。


# 1. 什么是异常?

异常 (Exception) 是程序在执行期间发生的错误事件。当 Python 解释器遇到一个它无法处理的错误情况时(例如,除以零、访问不存在的列表索引),它会创建一个异常对象并“抛出”它。

如果这个异常没有被程序的任何部分“捕获”并处理,程序就会立即终止,并显示一个称为“回溯 (Traceback)”的错误消息。

# 示例1:除以零
# result = 10 / 0
# Traceback (most recent call last):
#   File "<stdin>", line 1, in <module>
# ZeroDivisionError: division by zero

# 示例2:类型错误
# result = '2' + 3
# Traceback (most recent call last):
#   File "<stdin>", line 1, in <module>
# TypeError: can only concatenate str (not "int") to str
1
2
3
4
5
6
7
8
9
10
11

异常处理的核心目标就是:在异常发生时,捕获它,执行一些补救或记录措施,然后让程序继续执行(如果可能),而不是直接崩溃。


# 2. try...except:捕获异常

try...except 语句块是 Python 异常处理的基础。

  • try 块: 将你预感可能会出错的代码放在这里。
  • except 块: 如果 try 块中的代码真的发生了异常,解释器会立即跳转到 except 块来执行这里的代码。

基本语法:

try:
    # 可能会引发异常的代码
    code_that_might_fail()
except ExceptionType:
    # 如果发生了指定类型的异常,执行这里的代码
    handle_the_error()
1
2
3
4
5
6

示例:处理用户输入

try:
    num_str = input("请输入一个数字: ")
    num = int(num_str)
    print(f"你输入的数字是: {num}")
except ValueError:
    # 如果用户输入的不是有效的数字字符串,int() 会引发 ValueError
    print("错误:请输入一个有效的整数!")

print("程序继续执行...")
# 如果没有 try...except,当用户输入 "abc" 时,程序会崩溃。
# 有了它,程序会打印错误信息,然后继续执行到这里。
1
2
3
4
5
6
7
8
9
10
11

# 2.1 捕获特定异常

捕获过于宽泛的异常(如 Exception)或使用裸露的 except: 是一种不好的做法,因为它会掩盖所有类型的错误,让你难以调试。最佳实践是尽可能精确地捕获你预期的异常。

try:
    numerator = int(input("输入分子: "))
    denominator = int(input("输入分母: "))
    result = numerator / denominator
    print(f"结果是: {result}")
except ValueError:
    print("错误:分子和分母都必须是整数。")
except ZeroDivisionError:
    print("错误:分母不能为零!")
1
2
3
4
5
6
7
8
9

# 2.2 一次捕获多种异常

你可以将多个异常类型放在一个元组里,用一个 except 块来处理。

try:
    # ... 一些代码 ...
    pass
except (TypeError, ValueError, IndexError):
    print("发生了类型、值或索引错误。")
1
2
3
4
5

# 2.3 获取异常对象

有时,你需要获取异常对象的具体信息(例如,错误消息)。可以使用 as 关键字。

try:
    with open("non_existent_file.txt", "r") as f:
        content = f.read()
except FileNotFoundError as e:
    print("文件未找到!")
    print(f"详细错误信息: {e}")
    print(f"异常类型: {type(e)}")

# 输出:
# 文件未找到!
# 详细错误信息: [Errno 2] No such file or directory: 'non_existent_file.txt'
# 异常类型: <class 'FileNotFoundError'>
1
2
3
4
5
6
7
8
9
10
11
12

# 3. try...except...else 结构

else 子句提供了一种方式,用于指定当 try 块中没有发生任何异常时才需要执行的代码。

为什么要用 else? 它可以帮助你将可能引发异常的代码(放在 try 中)与仅在成功后才应执行的代码(放在 else 中)清晰地分开,提高代码可读性。

try:
    numerator = int(input("输入分子: "))
    denominator = int(input("输入分母: "))
    result = numerator / denominator
except ValueError:
    print("请输入有效的整数。")
except ZeroDivisionError:
    print("分母不能为零!")
else:
    # 只有在 try 块中所有语句都成功执行后,这里才会执行
    print("计算成功!")
    print(f"结果是: {result}")
1
2
3
4
5
6
7
8
9
10
11
12

# 4. try...finally:确保执行清理

finally 子句中的代码无论是否发生异常,都保证会被执行。这使得它成为执行“清理”操作(如关闭文件、释放网络连接、解锁资源)的理想场所。

f = None # 在 try 外面初始化
try:
    f = open("my_file.txt", "w")
    f.write("你好,Python!")
    # 假设这里发生了一个错误
    # 10 / 0
except Exception as e:
    print(f"发生了一个错误: {e}")
finally:
    # 无论上面是否出错,这里都会执行
    if f:
        print("正在关闭文件...")
        f.close()
1
2
3
4
5
6
7
8
9
10
11
12
13

注意: 更 Pythonic 的方式是使用 with 语句来管理资源,它会自动处理文件的打开和关闭,即使发生异常也是如此,这在内部其实就是利用了 try...finally。


# 5. raise:主动抛出异常

你可以使用 raise 关键字在代码中主动地、显式地引发一个异常。

为什么要主动抛出异常? 当你的函数接收到不合法的参数,或者程序进入了一个不正常的状态时,你可以通过抛出异常来立即终止当前操作,并通知调用者“出错了”。

def set_age(age):
    if not isinstance(age, int) or age < 0 or age > 120:
        # 如果年龄不合法,就抛出 ValueError 异常
        raise ValueError("年龄必须是 0 到 120 之间的整数!")
    print(f"年龄已设置为: {age}")

try:
    set_age(25)   # 正常
    set_age(-5)   # 引发异常
except ValueError as e:
    print(f"设置年龄失败: {e}")

# 输出:
# 年龄已设置为: 25
# 设置年龄失败: 年龄必须是 0 到 120 之间的整数!
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# 6. 自定义异常

虽然 Python 的内置异常已经很丰富,但有时你需要创建自己的异常类型来表示应用程序特有的错误情况。

自定义异常通过继承内置的 Exception 类(或其子类)来创建。

# 1. 创建自定义异常类
class NetworkError(Exception):
    """表示网络相关的错误"""
    def __init__(self, message, error_code):
        super().__init__(message) # 调用父类的构造函数
        self.error_code = error_code

# 2. 在代码中使用它
def fetch_data_from_server():
    # 模拟一个网络错误
    is_connected = False
    if not is_connected:
        raise NetworkError("无法连接到服务器", 503)

# 3. 捕获自定义异常
try:
    fetch_data_from_server()
except NetworkError as e:
    print(f"捕获到网络错误: {e}")
    print(f"错误码: {e.error_code}")
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

自定义异常的好处:

  • 更具描述性: NetworkError 比通用的 Exception 能更清晰地表达错误类型。
  • 更好的组织: 调用者可以专门捕获你的 NetworkError,并与其他的 ValueError 或 TypeError 区分开来。
  • 可扩展性: 你可以在异常中添加额外的属性(如 error_code),携带更多关于错误的上下文信息。

# 7. 常见内置异常

了解 Python 的常用内置异常对于编写健壮的代码至关重要。以下是一些最常见的异常及其触发条件:

  • ValueError: 传入的参数类型正确,但值不合适。

    # int() 无法将 "abc" 转换为整数
    int("abc") 
    
    1
    2
  • TypeError: 对不同类型的对象执行了不支持的操作。

    # 字符串不能和数字相加
    "2" + 3 
    
    1
    2
  • IndexError: 试图访问序列(如列表、元组)中不存在的索引。

    my_list = [1, 2, 3]
    print(my_list[3]) # 索引只到 2
    
    1
    2
  • KeyError: 试图访问字典中不存在的键。

    my_dict = {"name": "Alice"}
    print(my_dict["age"]) # "age" 键不存在
    
    1
    2
  • FileNotFoundError: 试图打开一个不存在的文件。

    with open("ghost.txt", "r") as f:
        pass
    
    1
    2
  • ZeroDivisionError: 尝试将一个数除以零。

    result = 10 / 0
    
    1
  • AttributeError: 试图访问或调用一个对象不存在的属性或方法。

    my_string = "hello"
    my_string.append("!") # 字符串没有 .append() 方法,那是列表的
    
    1
    2
  • NameError: 使用了一个未被定义的变量。

    print(undefined_variable)
    
    1

# 8. 异常处理最佳实践

  1. 精确捕获:尽量捕获最具体的异常,避免使用裸露的 except:。
  2. 不要压制异常:避免空的 except 块(except: pass),因为它会悄无声息地吞掉错误,让调试变得异常困难。如果你确实需要忽略某个异常,最好加上注释说明原因。
  3. 保持 try 块短小:只在 try 块中放入你真正认为可能出错的代码。
  4. 利用 finally 进行清理:使用 finally 来确保重要的清理代码(如关闭文件)总能执行,或者优先使用 with 语句。
  5. 创建自定义异常:为你的库或应用创建有意义的自定义异常,使错误处理更有条理。
  6. 记录异常:在捕获异常后,使用 logging 模块记录详细的错误信息,这对于生产环境中的问题排查至关重要。
编辑此页 (opens new window)
上次更新: 2025/07/23, 06:33:16
装饰器与生成器
标准库精讲

← 装饰器与生成器 标准库精讲→

Theme by Vdoing | Copyright © 2019-2025 程序员scholar
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式