当前位置: 首页 > 知识库问答 >
问题:

在处理上述异常期间,发生了另一个异常

魏鹤轩
2023-03-14

我在下面尝试捕获JSON解析错误:

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

为什么在处理上述异常时,打印出另一个异常,以及如何解决它?

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)

共有3个答案

颛孙轩昂
2023-03-14

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引发了一个异常,但是关闭也意外地引发了异常。当这种情况发生时,很高兴知道这两个例外。在大多数情况下,您想知道由write_data引发的原始异常,但是了解关闭引发的异常有助于您知道关闭发生了一些奇怪的事情。

但对于您的情况,您只是以一种新的方式重新启动原始错误。这样做可以提供更多上下文,例如:

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您实际上是在重新引发原始异常,但是需要更多的上下文,您可以从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中的“异常链接”,在这里您将原始异常提供给新异常的构造函数

姬坚成
2023-03-14

由于您正在从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

要抑制第一个,只记录无效json…异常。

顺便说一句,像raiseexception('Invalid json:{}.format(e))这样的操作并没有多大意义,在这一点上,您可以不处理原始异常,因为您没有向它添加太多信息。

屈畅
2023-03-14

目前,您遇到了在另一个捕获的异常中引发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文档解释了如何在异常警告中抑制这些异常。

 类似资料:
  • 我正在尝试实现遗传算法,程序在第一代后终止。。不知道为什么。。代码如下。。提出的异常是。。 文件"C:\用户\伊山\AppData\本地\程序\Python\Python36\lib\random.py",第255行,选择i=自己。_randbelow(len(seq))文件"C:\用户\伊山\AppData\本地\程序\Python\Python36\lib\random.py",第232行,_

  • 有人能简单地解释一下如何将我的域对象添加到apachemq可信对象吗。已经仔细阅读了apache教程,其中说需要将脚本添加到/bin/env,但我的bin文件夹中没有env文件。谢谢 2016-04-08 16:55:49错误提示控制器:23-控制器方面:方法例外-

  • 1.【强制】不要捕获Java类库中定义的继承自RuntimeException的运行时异常类,如:IndexOutOfBoundsException / NullPointerException,这类异常由程序员预检查来规避,保证程序健壮性。 正例:if(obj != null) {...} 反例:try { obj.method() } catch(NullPointerException e)

  • 这并不是关于如何在Spring MVC或任何东西中处理异常。我特别需要处理spring启动时可能发生的异常,即在初始化整个应用程序上下文之前。 作为一个背景,所讨论的应用程序是一个物联网节点,允许远程访问电子设备。它内置了一个小h2数据库来保存一些数据。这些数据有时很好,但对应用程序的工作来说并不是真正必要的。 很可能应用程序运行的设备每隔一段时间就会断电一次,如果在对数据库进行写入操作时发生这种

  • Apache Camel中是否有任何内置机制来延迟上次路由处理过程中发生异常时的下一次路由触发时间? 例如,如果我有一条路由: null

  • 在Spring Boot上下文的初始化过程中,有什么方法可以处理异常吗? 我的案例是在作业执行过程中处理错误,并根据发生的异常做一些工作。 例如,我有一个由读者和作家组成的工作。读取器和写入器使用以下属性初始化:rootFolder、inFolder、outfolder。这个简单的作业从/rootfolder/infolder/test.txt读取文件,并将数据写入rootfolder/outfo