Python 中除 Ecception 外的三类系统异常

KeyboardInterrupt、SystemExit、 GeneratorExit

1、python 内置的异常 层次结构

  • 四大系统级异常 (直接继承BaseException)

    python 复制代码
    异常类型	          触发场景	            代码设计建议捕获	            原因
    Exception        所有常规异常的父类        其子类 ✅ 应该	   常规程序错误,应该处理
    KeyboardInterrupt	用户按 Ctrl+C	        ⚠️ 谨慎	           仅用于清理资源,不要完全忽略
    SystemExit	        sys.exit() 调用	        ❌ 不建议	      让程序正常退出,除非有特殊需求
    GeneratorExit	    生成器关闭	            ❌ 不需要	      生成器内部通常不需要处理

2、KeyboardInterrupt 异常捕获

  • 捕获后可以执行清理操作,而不是立即终止程序。
python 复制代码
try:
    print("按Ctrl+C中断程序...")
    while True:
        pass  # 无限循环
except KeyboardInterrupt:
    print("\n捕获到键盘中断!")
    print("可以优雅地清理资源...")

# 用户按Ctrl+C后输出:
# 按Ctrl+C中断程序...
# 捕获到键盘中断!
# 可以优雅地清理资源...

3、SystemExit 异常捕获

  • 捕获后程序不会退出,除非再次raise或调用sys.exit()
python 复制代码
import sys

try:
    print("程序即将退出...")
    sys.exit(42)  # 退出代码42
except SystemExit as e:
    print(f"捕获到SystemExit,退出代码: {e.code}")
    # 可以选择阻止退出
    print("程序继续运行!")

# 输出:
# 程序即将退出...
# 捕获到SystemExit,退出代码: 42
# 程序继续运行!

4、GeneratorExit 异常捕获

  • 当生成器被close()或垃圾回收时,会在生成器内部抛出GeneratorExit。
python 复制代码
def my_generator():
    try:
        print("生成器开始运行")
        for i in range(10):
            yield i
    except GeneratorExit:
        print("生成器被关闭!")
        raise  # 重新抛出,或者选择不抛出

gen = my_generator()
print(next(gen))  # 0
print(next(gen))  # 1
gen.close()       # 关闭生成器

# 输出:
# 生成器开始运行
# 0
# 1
# 生成器被关闭!

5、实际捕获行为对比,一个完整例子展示所有四种:

python 复制代码
import sys
import time

def demo_system_exit():
    try:
        print("\n=== 测试 SystemExit ===")
        sys.exit(100)
    except SystemExit as e:
        print(f"✓ 捕获SystemExit,退出代码: {e.code}")
        print("  程序没有退出,继续执行...")

def demo_keyboard_interrupt():
    try:
        print("\n=== 测试 KeyboardInterrupt ===")
        print("  按Ctrl+C中断...")
        while True:
            time.sleep(0.1)
    except KeyboardInterrupt:
        print("\n✓ 捕获KeyboardInterrupt")
        print("  程序优雅退出...")

def demo_generator_exit():
    print("\n=== 测试 GeneratorExit ===")
    def generator():
        try:
            for i in range(5):
                yield i
        except GeneratorExit:
            print("  ✓ 捕获GeneratorExit")
            raise  # 重新抛出
    
    gen = generator()
    print(f"  生成值: {next(gen)}")
    print(f"  生成值: {next(gen)}")
    gen.close()  # 触发GeneratorExit

def demo_exception():
    try:
        print("\n=== 测试 Exception ===")
        raise ValueError("测试错误")
    except Exception as e:
        print(f"✓ 捕获Exception子类: {type(e).__name__}")
        print(f"  消息: {e}")

# 执行所有测试
demo_system_exit()
demo_generator_exit()
demo_exception()
# demo_keyboard_interrupt()  # 需要手动按Ctrl+C测试
  • 好的实践

    python 复制代码
    # 场景1:处理常规异常
    try:
        data = risky_operation()
    except ValueError as e:
        print(f"参数错误: {e}")
    except (IndexError, KeyError) as e:
        print(f"访问错误: {e}")
    except Exception as e:
        print(f"未知错误: {e}")
        logger.exception("发生异常")
    
    # 场景2:捕获KeyboardInterrupt进行清理
    try:
        main_loop()
    except KeyboardInterrupt:
        print("\n收到中断信号...")
        cleanup_resources()
        print("资源清理完成,退出。")
        sys.exit(0)  # 明确退出    
  • ❌ 不好的实践

    python 复制代码
    # 过度捕获KeyboardInterrupt
    try:
        everything()
    except KeyboardInterrupt:
        print("用户想退出,但我不让他退出!")
        # 继续运行... 这会让用户困惑
    
    # 捕获SystemExit阻止程序退出
    try:
        sys.exit(1)
    except SystemExit:
        print("程序想退出,但我不允许!")
        # 继续运行... 这会破坏退出逻辑
相关推荐
开发者小天13 分钟前
python中的class类
开发语言·python
idwangzhen22 分钟前
GEO优化系统哪家更专业
python·信息可视化
diediedei39 分钟前
机器学习模型部署:将模型转化为Web API
jvm·数据库·python
m0_5613596741 分钟前
使用Python自动收发邮件
jvm·数据库·python
naruto_lnq1 小时前
用Python批量处理Excel和CSV文件
jvm·数据库·python
b2077211 小时前
Flutter for OpenHarmony 身体健康状况记录App实战 - 提醒设置实现
python·flutter·macos·cocoa·harmonyos
2301_822365031 小时前
数据分析与科学计算
jvm·数据库·python
河北小博博1 小时前
分布式系统稳定性基石:熔断与限流的深度解析(附Python实战)
java·开发语言·python
黄连升1 小时前
Python学习第二天,系统学习基础
python·学习
西红市杰出青年2 小时前
CSS 选择器详细教程:原理、语法、方向/“轴”与实战
css·python