python-3.x 在处理上述异常的过程中,发生了另一个异常

rxztt3cl  于 2023-01-10  发布在  Python
关注(0)|答案(4)|浏览(119)

我有下面的try-except来捕捉JSON解析错误:

with open(json_file) as j:
    try:
        json_config = json.load(j)
    except ValueError as e:
        raise Exception('Invalid json: {}'.format(e))

为什么打印出During handling of the above exception, another exception occurred,如何解决?

json.decoder.JSONDecodeError: Expecting ',' delimiter: line 103 column 9 (char 1093)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
<....>
raise Exception('Invalid json: {}'.format(e))
Exception: Invalid json: Expecting ',' delimiter: line 103 column 9 (char 1093)
wpx232ag

wpx232ag1#

目前,您遇到了在另一个捕获的异常中引发ValueError异常的问题。这个解决方案的理由对我来说没有多大意义,但如果您更改它。

raise Exception('Invalid json: {}'.format(e))

raise Exception('Invalid json: {}'.format(e)) from None

做你的结束代码。

with open(json_file) as j:
    try:
        json_config = json.load(j)
    except ValueError as e:
        raise Exception('Invalid json: {}'.format(e)) from None

您应该会得到所需的捕获异常的结果。
例如:

>>> foo = {}
>>> try:
...     var = foo['bar']
... except KeyError:
...     raise KeyError('No key bar in dict foo') from None
...
Traceback (most recent call last):
  File "<stdin>", line 4, in <module>
KeyError: 'No key bar in dict foo'

对不起,我不能解释为什么这工作的确切原因,但它似乎做的伎俩。

**更新:**看起来有一个PEP doc解释了如何在异常警告中抑制异常。

idv4meu8

idv4meu82#

因为你在except语句中引发了另一个异常,python只是告诉你这一点。
换句话说,通常你使用except来处理一个异常,而不是让程序失败,但是在这种情况下,你在处理一个异常的同时引发了另一个异常,这就是python告诉你的。
如果这是你想要的行为,那真的没什么好担心的,如果你想“摆脱”那个消息,你可以在不引发另一个异常的情况下写一些东西到输出中,或者只是在不使用try/except语句的情况下第一次暂停程序。
正如Steven所建议的,您可以:

raise Exception('Invalid json: {}'.format(e)) from e

来打印两个异常,如下所示:

Traceback (most recent call last):
  File "tmp.py", line 5, in <module>
    raise Exception('Invalid json: {}'.format(e)) from e
Exception

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  <...>
    json.decoder.JSONDecodeError: Expecting ',' delimiter: line 103 column 9 (char 1093)

或者你可以这样做:

raise Exception('Invalid json: {}'.format(e)) from None

以抑制第一个异常并仅记录Invalid json...异常。
顺便说一句,像raise Exception('Invalid json: {}'.format(e))这样做实际上没有多大意义,此时您可以只保留原始异常,因为您没有向它添加太多信息。

vsdwdz23

vsdwdz233#

Python提醒你,当另一个异常正在处理的时候,你抛出了一个异常。这个警告是为了提醒你,如果这是意料之外的,那么你就可以知道最初的异常了。考虑下面的例子:

class Resource:
  def close(self):
     if cannot_close:
       raise Error("Cannot close")

  def write_data(self, data):
     ...

some_function():
  try:
    res = Resource()
    res.write_data("some data")
  except Error as e:
    res.close()

假设write_data引发了一个异常,但是close也意外地引发了异常。当这种情况发生时,了解这两个异常是很好的。在大多数情况下,你想了解write_data引发的原始异常,但是了解close引发的异常有助于你知道close发生了一些奇怪的事情。
但是对于您的情况,您只是以一种新的方式重述原始错误,这样做可以提供更多的上下文,例如:

with open(json_file) as j:
    try:
        json_config = json.load(j)
    except ValueError as e:
        raise Exception('Invalid json from file {}: {}'.format(json_file, e))

这将为您提供未能解析为JSON的文件的路径,这是有用的上下文信息,不会出现在原始异常消息中。
所以为了告诉Python你实际上是在重新引发最初的异常,但是有更多的上下文,你添加了from e

with open(json_file) as j:
    try:
        json_config = json.load(j)
    except ValueError as e:
        raise Exception('Invalid json from file {}: {}'.format(json_file, e)) from e

这等效于Java中的“异常链”,即向新异常的构造函数提供原始异常。

vptzau2j

vptzau2j4#

我用data.get(key)代替data[key]解决了这个问题。

相关问题