page contents

别再 except Exception: pass 了,Python 异常处理的正确姿势

BaseException 是顶级父节点,Exception 是 它的常用子类, 我们日常碰到的 ValueError、TypeError、KeyError、FileNotFoundError 都是 Exception 的子节点。

attachments-2026-08-O51UXyhp6a792d8729944.png小牛上周上线了一段代码,里面写了好几处  except Exception: pass

他觉得这样保险,出错了程序也不会崩。

结果上线当周,上游的一个接口返回格式变了,没有通知下游,系统异常被静默吞噬,整个下游数据全部错乱。

排查后才发现问题,就是因为那个 pass 把错误隐藏起来了。

编码中,暴露异常和兼容预防考验码农的攻守之道。

 

异常处理解决的问题场景

很多人写异常处理的逻辑是:出错就 catch,catch 完就 pass,程序不崩就行。

这样的坏处显而易见,异常没有被正确处理,反而留下了隐患。

Python 的异常体系是个树状结构。

BaseException 是顶级父节点,Exception 是 它的常用子类, 我们日常碰到的 ValueError、TypeError、KeyError、FileNotFoundError 都是 Exception  的子节点。

每个异常类型对应一种明确的错误场景:

 

int('abc')           # ValueError: 传入的值无法转换{}.get('a', 0) + '1'  # TypeError: 不能把 int 和 str 相加d = {}                # KeyError: d['key'] 键不存在open('no_such.txt')   # FileNotFoundError: 文件不存在

Python 还支持 else 和 finally 两个可选分支,但是很多人不知道。try 内部放置可能出错的代码,else 放置成功后要做的事,finally 里放置必须要执行的逻辑。

这种分层结构比把所有逻辑塞进 try 里清晰得多。

 

异常处理的三种境界

第一层:捕获具体的异常

 

# bad casetry:    result = api_call()except:    pass
# good casetry:    result = api_call()except ConnectionError:    print('网络连接失败,检查网络配置')except TimeoutError:    print('请求超时,服务端可能负载过高')

捕获越具体,定位问题越快。

except Exception 是底线, except: 裸捕获是禁区。

第二层:用 else + finally 管理流程

 

# bad case:所有逻辑塞 try 里try:    f = open('data.csv')    lines = f.readlines()    process(lines)    f.close()except:    pass
# good case:职责分离try:    f = open('data.csv')except FileNotFoundError:    print('数据文件不存在')else:    lines = f.readlines()    process(lines)finally:    f.close()

第三层:上下文管理器,自动清理资源

 

# with 语句就是上下文管理器的语法糖try:    with open('data.csv') as f:        lines = f.readlines()        process(lines)except FileNotFoundError:    print('数据文件不存在')except PermissionError:    print('没有读取权限')

with 语句会在代码块结束时自动调用 exit,不管有没有异常。open()、数据库连接、网络连接都支持 with,使用中优先用它。

 

异常处理的设计思想

异常处理的核心原则是:暴露问题,而不是隐藏问题。

Python 的 EAFP(Easier to Ask for Forgiveness than Permission)哲学鼓励你先做,出了异常再处理。这比先判断再做(LBYL)更 Pythonic,但前提是你的异常处理逻辑真的在秉公执法,而不是在大赦天下。

except: pass 的本质是:我知道这里可能出错,但我不想管,就当没发生。这种代码在调试阶段会让你找不到 bug,在生产阶段会让错误静默传播。

什么时候该 catch,什么时候该抛出异常?

如果当前函数能处理这个异常(比如重试、降级、返回默认值),就 catch。如果处理不了,就别 catch,让调用方决定怎么处理。

 

新手常见坑

为什么不能裸用 except?

except: 会捕获 KeyboardInterrupt(Ctrl+C)和 SystemExit(sys.exit()),连程序正常退出都会被拦截。调试时你想 Ctrl+C 终止程序,结果发现没反应,就是因为有人写了裸 except。

except 多个异常怎么写?

 

try:    result = risky_operation()except (ValueError, TypeError) as e:    print(f'参数错误: {e}')except (ConnectionError, TimeoutError) as e:    print(f'网络异常: {e}')

用元组把同类异常包在一起,不同类异常分开 catch。

异常信息怎么拿到?

 

try:    result = risky_operation()except ValueError as e:    print(f'错误信息: {e}')    print(f'异常类型: {type(e).__name__}')

as e 把异常对象赋给变量,e 里包含错误信息。

 

一句话总结:捕获具体异常,让错误暴露,别用 pass 逃避问题。

更多相关技术内容咨询欢迎前往并持续关注好学星城论坛了解详情。

想高效系统的学习Python编程语言,推荐大家关注一个微信公众号:Python编程学习圈。每天分享行业资讯、技术干货供大家阅读,关注即可免费领取整套Python入门到进阶的学习资料以及教程,感兴趣的小伙伴赶紧行动起来吧。

attachments-2022-05-rLS4AIF8628ee5f3b7e12.jpg

 

你可能感兴趣的文章

相关问题

0 条评论

请先 登录 后评论
Pack
Pack

2307 篇文章

作家榜 »

  1. 轩辕小不懂 2403 文章
  2. Pack 2307 文章
  3. 小柒 2228 文章
  4. Nen 576 文章
  5. 王昭君 209 文章
  6. 文双 71 文章
  7. 小威 64 文章
  8. Cara 36 文章