如何确定发生了什么类型的异常?

新手上路,请多包涵

some_function() 执行时引发异常,因此程序跳转到 except

 try:
    some_function()
except:
    print("exception happened!")

如何查看导致异常发生的原因?

原文由 Shang Wang 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 429
2 个回答

其他答案都指出您不应该捕获通用异常,但似乎没有人想告诉您原因,这对于理解何时可以打破“规则”至关重要。 是一个解释。基本上,这样你就不会隐藏:

因此,只要您注意不做任何这些事情,就可以捕获通用异常。例如,您可以通过另一种方式向用户提供有关异常的信息,例如:

  • 在 GUI 中将异常显示为对话框
  • 将异常从工作线程或进程转移到多线程或多处理应用程序中的控制线程或进程

那么如何捕捉泛型异常呢?有几种方法。如果您只想要异常对象,请这样做:

 try:
    someFunction()
except Exception as ex:
    template = "An exception of type {0} occurred. Arguments:\n{1!r}"
    message = template.format(type(ex).__name__, ex.args)
    print message

确保 message 以一种不容错过的方式引起用户的注意!如果消息隐藏在许多其他消息中,打印它,如上所示,可能还不够。没有引起用户的注意,就等于吞下了所有的例外,如果你在阅读本页的答案后有一个印象,那就是这 _不是一件好事_。以 raise 语句结束 except 块将通过透明地重新引发捕获的异常来解决问题。

上面和只使用 except: 没有任何参数的区别是双重的:

  • 一个光秃秃的 except: 不会给你异常对象来检查
  • 异常 SystemExitKeyboardInterruptGeneratorExit 没有被上面的代码捕获,这通常是你想要的。请参阅 异常层次结构

如果您还想要在未捕获异常的情况下获得相同的堆栈跟踪,则可以这样获得(仍在 except 子句中):

 import traceback
print traceback.format_exc()

如果您使用 logging 模块,您可以将异常打印到日志(连同一条消息),如下所示:

 import logging
log = logging.getLogger()
log.exception("Message for you, sir!")

如果您想深入挖掘并检查堆栈、查看变量等,请使用 except 块内的 pdb 模块的 post_mortem 函数:

 import pdb
pdb.post_mortem()

在寻找错误时,我发现最后一种方法非常有用。

原文由 Lauritz V. Thaulow 发布,翻译遵循 CC BY-SA 3.0 许可协议

获取异常对象所属类的名称:

 e.__class__.__name__

并且使用 print_exc() 函数还将打印堆栈跟踪,这是任何错误消息的基本信息。

像这样:

 from traceback import print_exc

class CustomException(Exception): pass

try:
    raise CustomException("hi")
except Exception as e:
    print ('type is:', e.__class__.__name__)
    print_exc()
    # print("exception happened!")

你会得到这样的输出:

 type is: CustomException
Traceback (most recent call last):
  File "exc.py", line 7, in <module>
    raise CustomException("hi")
CustomException: hi

在打印和分析之后,代码可以决定不处理异常而只执行 raise

 from traceback import print_exc

class CustomException(Exception): pass

def calculate():
    raise CustomException("hi")

try:
    calculate()
except CustomException as e:
    # here do some extra steps in case of CustomException
    print('custom logic doing cleanup and more')
    # then re raise same exception
    raise

输出:

 custom logic doing cleanup and more

解释器打印异常:

 Traceback (most recent call last):
  File "test.py", line 9, in <module>
    calculate()
  File "test.py", line 6, in calculate
    raise CustomException("hi")
__main__.CustomException: hi

raise 之后,原始异常继续向上传播调用堆栈。 ( 当心可能的陷阱)如果你提出新的异常,它会带来新的(更短的)堆栈跟踪。

 from traceback import print_exc

class CustomException(Exception):
    def __init__(self, ok):
        self.ok = ok

def calculate():
    raise CustomException(False)

try:
    calculate()
except CustomException as e:
    if not e.ok:
        # Always use `raise` to rethrow exception
        # following is usually mistake, but here we want to stress this point
        raise CustomException(e.ok)
    print("handling exception")

输出:

 Traceback (most recent call last):
  File "test.py", line 13, in <module>
    raise CustomException(e.message)
__main__.CustomException: hi

注意回溯如何不包括 calculate() 行中的函数 9 这是原始异常的起源 e

原文由 Alex 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题