python:我如何知道发生了什么类型的异常?

2024-04-26 04:28:55 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个主程序调用的函数:

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

但在执行函数的过程中,它会引发异常,因此它会跳到except部分。

我如何才能确切地看到导致异常发生的someFunction()中发生了什么?


Tags: 函数过程exceptionprinttryexcept主程序somefunction
3条回答

其他的答案都指出,你不应该捕捉一般的异常,但似乎没有人想告诉你为什么,这对于理解何时可以打破“规则”是至关重要的。Here是一种解释。基本上,这样你就不会隐藏:

所以只要你不去做这些事情,就可以捕捉一般的异常。例如,您可以通过另一种方式向用户提供有关异常的信息,例如:

  • 在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

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

上述方法与只使用except:而不使用任何参数的方法之间的区别有两个:

  • 一个空的except:不会给您提供要检查的异常对象
  • 异常SystemExitKeyboardInterruptGeneratorExit不会被上述代码捕获,这通常是您想要的。请参阅exception hierarchy

如果您还希望得到相同的stacktrace,如果您没有捕获异常,您可以这样得到(仍然在except子句中):

import traceback
print traceback.format_exc()

如果使用^{}模块,则可以将异常打印到日志(连同消息)中,如下所示:

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

如果要深入挖掘并检查堆栈、查看变量等,请使用except块中pdb模块的^{}函数:

import pdb
pdb.post_mortem()

我发现最后一种方法在寻找虫子时是非常有用的。

您通常不应该捕捉到try: ... except中所有可能的异常,因为这过于宽泛。抓住那些不管什么原因都会发生的事情。如果您真的必须这样做,例如,如果您想在调试时发现有关某些问题的更多信息,您应该这样做

try:
    ...
except Exception as ex:
    print ex # do whatever you want for debugging.
    raise    # re-raise exception.

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

e.__class__.__name__

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

像这样:

from traceback import print_exc

class CustomException(Exception): pass

try:
    raise CustomException("hi")
except Exception, 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 Exception, e:
    if e.__class__ == CustomException:
        print 'special case of', e.__class__.__name__, 'not interfering'
        raise
    print "handling exception"

输出:

special case of CustomException not interfering

解释器打印异常:

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): pass

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

try:
    calculate()
except Exception, e:
    if e.__class__ == CustomException:
        print 'special case of', e.__class__.__name__, 'not interfering'
        #raise CustomException(e.message)
        raise e
    print "handling exception"

输出:

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

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

相关问题 更多 >