在没有回溯的情况下引发错误

4m1*_*4j1 4 python api wrapper

我想使用raise而不在屏幕上打印回溯。我知道如何用那做try ..catch,但是没有找到一个办法raise

下面是一个例子:

def my_function(self):
    resp = self.resp
    if resp.status_code == 404:
        raise NoSuchElementError('GET'+self.url+'{}'.format(resp.status_code)) 
    elif resp.status_code == 500:
        raise ServerErrorError('GET'+self.url+'{}'.format(resp.status_code))
Run Code Online (Sandbox Code Playgroud)

执行此操作时,如果我有 404,则回溯将打印在屏幕上。

Traceback (most recent call last):
  File "test.py", line 32, in <module>
    print ins.my_function()
  File "api.py", line 820, in my_function
    raise NoSuchElementError('GET ' + self.url + ' {} '.format(resp.status_code)) 
Run Code Online (Sandbox Code Playgroud)

这是一个 API 包装器,我不希望用户看到回溯,而是希望看到 API 响应代码和错误消息。

有没有办法做到这一点?

lej*_*lot 5

问题不在于引发任何问题,而在于当程序因异常终止时(它只是打印堆栈跟踪)时 python 解释器所做的事情。如果你想避免它,你应该做的就是在你想要“隐藏”堆栈跟踪的所有内容周围放置 try except 块,例如:

def main():
  try:
    actual_code()
  except Exception as e:
    print(e)
Run Code Online (Sandbox Code Playgroud)

另一种方法是修改异常处理程序,sys.excepthook(type, value, traceback)以执行您自己的逻辑,例如

def my_exchandler(type, value, traceback):
  print(value)

import sys
sys.excepthook = my_exchandler
Run Code Online (Sandbox Code Playgroud)

您甚至可以设置异常条件type并执行特定逻辑,当且仅当它是您的异常类型时,否则 - 退回到原始异常。


Ale*_*lec 5

我遇到了一个类似的问题,其中父类使用异常值raise来传递消息,但我不想转储回溯。@lejlot 提供了一个很好的解决方案,sys.excepthook但我需要在更有限的范围内应用它。这是修改:

import sys
from contextlib import contextmanager

@contextmanager
def except_handler(exc_handler):
    "Sets a custom exception handler for the scope of a 'with' block."
    sys.excepthook = exc_handler
    yield
    sys.excepthook = sys.__excepthook__
Run Code Online (Sandbox Code Playgroud)

然后,使用它:

def my_exchandler(type, value, traceback):
    print(': '.join([str(type.__name__), str(value)]))

with except_handler(my_exchandler):
    raise Exception('Exceptional!')

# -> Exception: Exceptional!
Run Code Online (Sandbox Code Playgroud)

这样,如果块中未引发异常,则默认异常处理将针对任何后续异常恢复:

with except_handler(my_exchandler):
    pass

raise Exception('Ordinary...')

# -> Traceback (most recent call last):
# ->   File "raise_and_suppress_traceback.py", line 22, in <module>
# ->     raise Exception('Ordinary...')
# -> Exception: Ordinary...
Run Code Online (Sandbox Code Playgroud)

  • 我喜欢这个答案......尽管在上下文管理器定义中使用“sys.excepthook = sys.__ excepthook__”行重置“sys.excepthook”将永远不会被执行。异常将首先执行,防止任何进一步的代码运行。因此,系统异常挂钩永远不会被重置,从而否定了上下文管理器的用处。即使按照“contextlib”文档的建议在“try/finally”块中使用,它也不起作用。在这种情况下,“finally”条件(即重置异常挂钩的位置)将在异常之前执行,从而导致使用预先存在的挂钩。 (2认同)

小智 5

修改后的@Alec答案

from contextlib import contextmanager

@contextmanager
def disable_exception_traceback():
    """
    All traceback information is suppressed and only the exception type and value are printed
    """
    default_value = getattr(sys, "tracebacklimit", 1000)  # `1000` is a Python's default value
    sys.tracebacklimit = 0
    yield
    sys.tracebacklimit = default_value  # revert changes
Run Code Online (Sandbox Code Playgroud)

用法:

with disable_exception_traceback():
    raise AnyYourCustomException()
Run Code Online (Sandbox Code Playgroud)

如果您只需要隐藏回溯而不修改异常消息,请使用此选项。在 Python 3.8 上测试

UPD:代码由 @DrJohnAStevenson 评论改进