为什么在捕获异常后无法再次调用它?

5 投票
1 回答
896 浏览
提问于 2025-04-17 21:49

为什么我在捕获一个异常类之后不能再抛出这个异常实例呢?奇怪的是,当我从一个函数里运行这个脚本时会遇到这个错误,但直接在Python命令行里运行却没有问题。

In [2]: def do():
   ...:     try:
   ...:         raise ValueError('yofoo')
   ...:     except TypeError, ValueError:
   ...:         raise ValueError('yo')
   ...: 

In [3]: do()
---------------------------------------------------------------------------
UnboundLocalError                         Traceback (most recent call last)
<ipython-input-3-30c46b84d9a4> in <module>()
----> 1 do()

<ipython-input-2-b62158d6343b> in do()
      1 def do():
      2     try:
----> 3         raise ValueError('yofoo')
      4     except TypeError, ValueError:
      5         raise ValueError('yo')

UnboundLocalError: local variable 'ValueError' referenced before assignment

这里预期会出现的错误:

In [3]: try:
   ...:     raise ValueError("foo")
   ...: except ValueError:
   ...:     raise ValueError("bar")
   ...: 
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-3-d5c83419a5ea> in <module>()
      2     raise ValueError("foo")
      3 except ValueError:
----> 4     raise ValueError("bar")
      5 

ValueError: bar

1 个回答

9
except TypeError, ValueError:

应该是

except (TypeError, ValueError):

当你使用 except TypeError, ValueError: 时,你实际上是把异常实例赋值给了变量名 ValueError

在你现在的代码中,当 Python 解析 do 函数时,它会注意到 ValueError 是一个局部变量,因为 except TypeError, ValueError:ValueError 赋了值。但是当你在第一个 try-suite 中引用它时,使用 raise ValueError('yofoo'),这个局部变量 ValueError 还没有值。所以你会遇到 UnboundLocalError 的错误。


来自 文档

... except (RuntimeError, TypeError, NameError):
...     pass

注意,这个元组周围的括号是必须的,因为 except ValueError, e: 是旧的语法,而现代 Python 中通常写作 except ValueError as e:(下面会描述)。旧语法仍然被支持以保持向后兼容。这意味着 except RuntimeError, TypeError 并不等同于 except (RuntimeError, TypeError):,而是等同于 except RuntimeError as TypeError:,这并不是你想要的。

撰写回答