我在我的代码中有这个try块:

try:
    do_something_that_might_raise_an_exception()
except ValueError as err:
    errmsg = 'My custom error message.'
    raise ValueError(errmsg)

严格地说,我实际上引发了另一个ValueError,而不是do_something…()抛出的ValueError,在这种情况下被称为err。如何将自定义消息附加到错误?我尝试以下代码,但失败,由于错误,ValueError实例,不可调用:

try:
    do_something_that_might_raise_an_exception()
except ValueError as err:
    errmsg = 'My custom error message.'
    raise err(errmsg)

当前回答

试试下面:

try:
    raise ValueError("Original message. ")
except Exception as err:
    message = 'My custom error message. '
    # Change the order below to "(message + str(err),)" if custom message is needed first. 
    err.args = (str(err) + message,)
    raise 

输出:

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
      1 try:
----> 2     raise ValueError("Original message")
      3 except Exception as err:
      4     message = 'My custom error message.'
      5     err.args = (str(err) + ". " + message,)

ValueError: Original message. My custom error message.

其他回答

如果你足够幸运只支持python 3。X,这真的变成了一件美丽的事情:)

提高从

我们可以使用raise from链接异常。

try:
    1 / 0
except ZeroDivisionError as e:
    raise Exception('Smelly socks') from e

在这种情况下,调用者将捕获的异常具有引发异常的位置的行号。

Traceback (most recent call last):
  File "test.py", line 2, in <module>
    1 / 0
ZeroDivisionError: division by zero

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

Traceback (most recent call last):
  File "test.py", line 4, in <module>
    raise Exception('Smelly socks') from e
Exception: Smelly socks

注意,底部异常只有我们引发异常的堆栈跟踪。调用者仍然可以通过访问他们捕获的异常的__cause__属性来获得原始异常。

with_traceback

或者你可以使用with_traceback。

try:
    1 / 0
except ZeroDivisionError as e:
    raise Exception('Smelly socks').with_traceback(e.__traceback__)

使用这种形式,调用者将捕获的异常具有原始错误发生位置的回溯。

Traceback (most recent call last):
  File "test.py", line 2, in <module>
    1 / 0
ZeroDivisionError: division by zero

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "test.py", line 4, in <module>
    raise Exception('Smelly socks').with_traceback(e.__traceback__)
  File "test.py", line 2, in <module>
    1 / 0
Exception: Smelly socks

注意,底部的异常中有执行无效除法的行,也有重新引发异常的行。

这只适用于Python 3。您可以修改异常的原始参数并添加自己的参数。

异常会记住创建它时使用的参数。我认为这样您就可以修改异常了。

在函数rerraise中,我们在异常的原始参数前加上我们想要的任何新参数(比如消息)。最后,我们在保留回溯历史的同时重新引发异常。

def reraise(e, *args):
  '''re-raise an exception with extra arguments
  :param e: The exception to reraise
  :param args: Extra args to add to the exception
  '''

  # e.args is a tuple of arguments that the exception with instantiated with.
  #
  e.args = args + e.args

  # Recreate the exception and preserve the traceback info so that we can see 
  # where this exception originated.
  #
  raise e.with_traceback(e.__traceback__)   


def bad():
  raise ValueError('bad')

def very():
  try:
    bad()
  except Exception as e:
    reraise(e, 'very')

def very_very():
  try:
    very()
  except Exception as e:
    reraise(e, 'very')

very_very()

输出

Traceback (most recent call last):
  File "main.py", line 35, in <module>
    very_very()
  File "main.py", line 30, in very_very
    reraise(e, 'very')
  File "main.py", line 15, in reraise
    raise e.with_traceback(e.__traceback__)
  File "main.py", line 28, in very_very
    very()
  File "main.py", line 24, in very
    reraise(e, 'very')
  File "main.py", line 15, in reraise
    raise e.with_traceback(e.__traceback__)
  File "main.py", line 22, in very
    bad()
  File "main.py", line 18, in bad
    raise ValueError('bad')
ValueError: ('very', 'very', 'bad')

引发相同的错误,并在前面添加自定义文本消息。 (编辑-抱歉,实际上和https://stackoverflow.com/a/65494175/15229310一样,为什么有10个(好评)“解决方案”只是不回答张贴的问题?)

    try:
       <code causing exception>
    except Exception as e:
        e.args = (f"My custom text. Original Exception text: {'-'.join(e.args)}",)
        raise

上面提出的许多解决方案再次引发异常,这被认为是一种糟糕的做法。像这样简单的东西就可以了

try:
    import settings
except ModuleNotFoundError:
    print("Something meaningfull\n")
    raise 

因此,您将首先打印错误消息,然后引发堆栈跟踪,或者您可以简单地通过sys.exit(1)退出,而根本不显示错误消息。

上面的解决方案都没有完全满足我的要求,即在错误消息的第一部分添加一些信息,即我希望我的用户首先看到我的自定义消息。

这招对我很管用:

exception_raised = False
try:
    do_something_that_might_raise_an_exception()
except ValueError as e:
    message = str(e)
    exception_raised = True

if exception_raised:
    message_to_prepend = "Custom text"
    raise ValueError(message_to_prepend + message)