finally块几乎总执行,但os._exit()、SIGKILL、解释器崩溃或断电等硬中断会跳过;sys.exit()仍触发finally;try/except中return后finally仍执行并可覆盖返回值。

Python finally 块在绝大多数情况下都会执行
是的,finally 块设计初衷就是「无论是否发生异常、是否提前 return、break 或 continue」,都要执行。这是它和 else(仅无异常时执行)最根本的区别。
但“一定”要加引号——存在极少数绕过它的场景,不是语言缺陷,而是 Python 运行时被强制终止的结果。
哪些情况会导致 finally 不执行
真正跳过 finally 的,是那些让解释器来不及跑完清理逻辑的硬性中断:
-
os._exit():直接退出进程,不触发任何 Python 级别的清理(包括finally、__del__、atexit) - 外部信号强制终止:比如
kill -9(SIGKILL),操作系统直接杀掉进程 - Python 解释器崩溃:如 C 扩展引发段错误(segfault)
- 电源断电、系统死机等物理级故障
注意:sys.exit() 会触发 finally,因为它只是抛出 SystemExit 异常,仍走正常异常处理流程。
立即学习“Python免费学习笔记(深入)”;
return 在 try/except 中遇到 finally 会怎样
这是最容易误解的点:即使 try 或 except 中有 return,finally 仍会执行,且它的 return 会覆盖前面的返回值。
def f():
try:
return "from try"
finally:
return "from finally"
print(f()) # 输出 "from finally"
更隐蔽的是:如果 finally 中没有 return,但修改了可变对象,会影响函数返回结果:
def g():
a = [1]
try:
return a
finally:
a.append(2) # 返回的 list 实际是 [1, 2]
print(g()) # 输出 [1, 2]
finally 不是万能的资源保护方案
它适合做“尽力而为”的清理,比如关闭文件句柄、释放锁、记录日志。但它不能替代更健壮的资源管理方式:
- 文件操作优先用
with语句,自动保证关闭,比手动try/finally更可靠 - 线程锁建议用上下文管理器或
threading.RLock的自动释放机制 - 若
finally里又抛出新异常,会压制原始异常(除非原始异常还没被处理)
真正关键的资源释放逻辑,别只靠 finally 撑着;尤其当程序可能被 os._exit() 或 SIGKILL 干掉时,finally 就彻底失效了。









