Python try-except-finally执行顺序规则验证及相关疑问
Python try-except-finally 执行顺序测试与验证
测试背景
之前很少使用finally代码块,为了规范使用先开展了测试,以下是测试过程和疑问。
第一段测试代码及结果
代码:
def f(): try: 1/0 # 1/1 except: print('except') # 1 raise # 2 finally: print('finally') # 3 try: f() except: print("haha")
执行结果:
except finally haha
总结的执行顺序规则及疑问
基于这段测试,我总结出执行顺序规则:
- 执行
except块中除raise语句(若存在)外的所有内容; - 执行
finally块; - 回到
except块执行raise语句(若存在)。
请问该规则是否正确?另外,except块中除raise外,是否还有其他会延迟到finally块之后执行的语句?
第二段测试示例(更直观)
代码:
def f(): try: 1/0 # 1/1 except: print('except') #1 raise print("a") #2 # 无实际意义,仅用于观察执行顺序 finally: print('finally') #3
执行结果:
except a finally foo
解答
你的总结方向是对的,但可以更精准地理解底层逻辑:
- 当
except块中出现raise时,raise的异常抛出动作会延迟到finally执行完成后,但raise语句里的表达式(比如第二段中的print("a"))会在当前位置立即执行,不会延迟。 - 除了
raise,return、break、continue这类改变控制流的语句,它们的生效动作也会被延迟到finally执行后。比如except块里写return 1,会先执行完finally的代码,再真正返回值。
举个return的验证例子:
def f(): try: 1/0 except: print('except') return 1 finally: print('finally') print(f())
执行结果:
except finally 1
这里return 1的返回动作要等finally执行完毕才会完成。
本质上,finally的设计核心就是:无论try/except块中发生什么(正常结束、抛出异常、return/break等),都会在离开try语句块前执行。所以当except块中有改变控制流的语句时,这些语句的“最终生效步骤”会被挂起,先执行finally,再完成控制流的变更。
内容的提问来源于stack exchange,提问作者Basj
相关产品推荐
相关产品推荐

