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

时间:2016-07-26 19:51:18

标签: 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))

执行此操作时,如果我有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)) 

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

有办法吗?

4 个答案:

答案 0 :(得分:3)

问题不在于提升任何东西,而在于python解释器的作用,当程序以异常终止时(它只是打印堆栈跟踪)。如果你想避免它,你应该做的是将try除了阻止你想要“隐藏”堆栈跟踪的所有内容,例如:

def main():
  try:
    actual_code()
  except Exception as e:
    print(e)

另一种方法是修改exeption处理程序sys.excepthook(type, value, traceback)来做你自己的逻辑,比如

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

import sys
sys.excepthook = my_exchandler

你甚至可以条件异常type并且如果它是你的异常类型则执行特定的逻辑,否则 - 退回原始异常。

答案 1 :(得分:3)

修改后的@Alec answer

end reconfigure

用法:

@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

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

UPD:通过@DrJohnAStevenson评论改进的代码

答案 2 :(得分:1)

捕获异常,记录并返回指示消费者出现问题的内容(当查询失败时发回200可能会导致客户端出现问题)。

try:
     return do_something()
except NoSuchElementError as e:
    logger.error(e)
    return error_response()

error_response()函数可以执行任何操作,返回空响应或错误消息。您仍应使用正确的HTTP状态代码。听起来你应该在这个例子中返回404。

您应该优雅地处理异常,但不应该完全隐藏客户端的错误。如果您的NoSuchElementError异常,则听起来应该通知客户端(错误可能在他们的结尾)。

答案 3 :(得分:1)

我遇到了类似的问题,其中父类使用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__

然后,使用它:

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

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

# -> Exception: Exceptional!

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

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...