为何Python中赋值变量时try块无法捕获异常?
问题场景
我编写了如下try-except块:
try: result = api.call_to_api(arg1, ar2) except: ValueError
通过单元测试调用这段代码时,我用unittest.mock.patch对api.call_to_api做了打桩:
@patch('api.call_to_api') def myTest(self, mock): mock.side_effect = [DEFAULT, ValueError] # 测试逻辑
测试时发现,第一个try块没有捕获到异常,反而成功给result完成了赋值。但当我把try块修改为以下形式时,就能正常触发异常捕获:
try: result = api.call_to_api(arg1, ar2) api.call_to_api(arg1, ar2) except: ValueError
此时单独占一行的api.call_to_api调用能触发try的异常捕获流程,且result仍被赋值为''。
问题核心
为什么Python中,当函数调用放在赋值语句右侧时,try块无法捕获它抛出的异常?
原因分析
问题出在你的except语法完全写错了:
你写的except: ValueError,实际是定义了一个无异常类型限制的except块(会捕获所有异常),然后在块内写了一个毫无意义的ValueError表达式——只是引用了这个异常类,没有任何处理逻辑。
当api.call_to_api第一次调用抛出ValueError时,这个错误的except块确实捕获了异常,但捕获后只执行了ValueError这个无效语句,随后程序就继续往下走了,result自然会被赋值为side_effect列表里的第一个值DEFAULT,所以看起来像是“没捕获到异常”。
当你添加了第二行api.call_to_api调用后,第二次调用触发side_effect里的ValueError,同样被这个except块捕获,此时你可能在测试里检测到了异常触发的行为,所以误以为“捕获成功”,但本质上还是语法错误导致的逻辑混乱。
正确的try-except写法
把语法改成except ValueError:,才能正确捕获指定类型的异常:
try: result = api.call_to_api(arg1, ar2) except ValueError: # 这里编写你的异常处理逻辑,比如: result = "" # 或者其他处理操作
修正语法后,赋值语句右侧函数抛出的ValueError会被正确捕获,result也不会被赋值为函数的返回值,而是进入你定义的异常处理流程。
内容的提问来源于stack exchange,提问作者Brad B.

