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

python:我如何知道发生了什么类型的异常?,python,exception,Python,Exception,我有一个主程序调用的函数: try: someFunction() except: print "exception happened!" 但是在执行函数的中间,它引发异常,所以它跳到代码> 部分。 我怎样才能准确地看到导致异常发生的someFunction()中发生了什么?通常不应该使用try:>捕获所有可能的异常。。。除了,因为这太宽泛了。不管出于什么原因,只要抓住那些可能发生的事情。如果您确实必须这样做,例如,如果您想在调试时了解有关某个问题的更多信息,您应该这样做 tr

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

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

但是在执行函数的中间,它引发异常,所以它跳到<>代码> 部分。


我怎样才能准确地看到导致异常发生的
someFunction()
中发生了什么?

通常不应该使用
try:>捕获所有可能的异常。。。除了
,因为这太宽泛了。不管出于什么原因,只要抓住那些可能发生的事情。如果您确实必须这样做,例如,如果您想在调试时了解有关某个问题的更多信息,您应该这样做

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

可以通过以下方式捕获实际异常:

try:
    i = 1/0
except Exception as e:
    print e

您可以从中了解有关异常的更多信息。

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

  • 发生错误的事实
  • 发生的错误的详细信息()
因此,只要您注意不做这些事情,就可以捕获一般异常。例如,您可以通过另一种方式向用户提供有关异常的信息,如:

  • 在GUI中将异常显示为对话框
  • 在多线程或多处理应用程序中,将异常从工作线程或进程转移到控制线程或进程
那么,如何捕获泛型异常呢?有几种方法。如果只需要exception对象,请按如下方式执行:

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
import logging
log = logging.getLogger()
log.exception("Message for you, sir!")
type is: CustomException
Traceback (most recent call last):
  File "exc.py", line 7, in <module>
    raise CustomException("hi")
CustomException: hi
确保
消息
以一种不容错过的方式引起用户的注意!如上图所示,如果消息被隐藏在许多其他消息中,打印它可能是不够的。没有引起用户的注意就等于吞没了所有的例外,如果你在阅读了本页的答案后有一种印象应该消失,那就是这不是一件好事。用
raise
语句结束except块将通过透明地重新调用捕获的异常来解决问题

以上与仅使用
除外:
而不使用任何参数之间的区别有两方面:

  • except:
    不会提供要检查的异常对象
  • 上述代码通常不会捕获异常
    SystemExit
    KeyboardInterrupt
    GeneratorExit
    。看
如果您还希望在未捕获异常时获得相同的stacktrace,可以这样获得(仍在except子句中):

如果使用该模块,您可以将异常打印到日志(以及消息),如下所示:

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
import logging
log = logging.getLogger()
log.exception("Message for you, sir!")
type is: CustomException
Traceback (most recent call last):
  File "exc.py", line 7, in <module>
    raise CustomException("hi")
CustomException: hi
如果要深入挖掘并检查堆栈、查看变量等,请在except块内使用
pdb
模块的函数:

import pdb
pdb.post_mortem()

我发现最后一个方法在查找bug时非常有用。

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

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!"
您将得到如下输出:

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
import logging
log = logging.getLogger()
log.exception("Message for you, sir!")
type is: CustomException
Traceback (most recent call last):
  File "exc.py", line 7, in <module>
    raise CustomException("hi")
CustomException: hi
输出:

special case of CustomException not interfering
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    
和解释器打印异常:

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
输出:

special case of CustomException not interfering
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    
CustomException不干扰的特殊情况
回溯(最近一次呼叫最后一次):
文件“test.py”,第13行,在
引发自定义异常(e.message)
__主\自定义异常:嗨

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

只要避免捕获异常,Python打印的回溯将告诉您发生了什么异常。

除非
somefunction
是一个非常糟糕的编码遗留函数,否则您不需要您所要求的

class general_function_handler(object):
    def __init__(self, func):
        self.func = func
    def __get__(self, obj, type=None):
        return self.__class__(self.func.__get__(obj, type))
    def __call__(self, *args, **kwargs):
        try:
            retval = self.func(*args, **kwargs)
        except Exception, e :
            logging.warning('Exception in %s' % self.func)
            template = "An exception of type {0} occured. Arguments:\n{1!r}"
            message = template.format(type(e).__name__, e.args)
            logging.exception(message)
            sys.exit(1) # exit on all exceptions for now
        return retval
使用多个
except
子句以不同的方式处理不同的异常:

try:
    someFunction()
except ValueError:
    # do something
except ZeroDivision:
    # do something else

主要的一点是,您不应该捕获泛型异常,而应该只捕获需要捕获的异常。我确信您不想隐藏意外的错误或bug。

在Python 2中,以下内容非常有用

except Exception, exc:

    # This is how you get the type
    excType = exc.__class__.__name__

    # Here we are printing out information about the Exception
    print 'exception type', excType
    print 'exception msg', str(exc)

    # It's easy to reraise an exception with more information added to it
    msg = 'there was a problem with someFunction'
    raise Exception(msg + 'because of %s: %s' % (excType, exc))

为了补充Lauritz的答案,我创建了一个用于异常处理的装饰器/包装器,包装器记录发生的异常类型

class general_function_handler(object):
    def __init__(self, func):
        self.func = func
    def __get__(self, obj, type=None):
        return self.__class__(self.func.__get__(obj, type))
    def __call__(self, *args, **kwargs):
        try:
            retval = self.func(*args, **kwargs)
        except Exception, e :
            logging.warning('Exception in %s' % self.func)
            template = "An exception of type {0} occured. Arguments:\n{1!r}"
            message = template.format(type(e).__name__, e.args)
            logging.exception(message)
            sys.exit(1) # exit on all exceptions for now
        return retval
这可以通过decorator在类方法或独立函数上调用:

@通用函数处理程序

有关完整示例,请参阅我的博客:

您的问题是:“如何准确地看到导致异常发生的someFunction()中发生了什么?”

在我看来,您并不是在问如何处理生产代码中不可预见的异常(正如许多答案所假设的那样),而是在开发过程中如何找出导致特定异常的原因


最简单的方法是使用一个调试器,它可以在发生未捕获异常时停止,最好不要退出,以便您可以检查变量。例如,Eclipse开源IDE中的PyDev可以做到这一点。要在Eclipse中启用该功能,请打开Debug透视图,在
运行
菜单中选择
管理Python异常断点
,然后选中
在未捕获异常时暂停
,您可以按照Lauritz的建议启动,包括:

except Exception as ex:
然后只需打印ex
,如下所示:

try:
    #your try code here
except Exception as ex:
    print ex

下面是我如何处理我的异常。我们的想法是尝试解决这个问题,如果这很容易,然后添加一个更理想的解决方案,如果可能的话。不要解决生成异常的代码中的问题,否则代码会丢失对原始算法的跟踪,而原始算法应该被写到点子上。但是,传递解决问题所需的数据,并返回lambda,以防在生成问题的代码之外无法解决问题

path = 'app.p'

def load():
    if os.path.exists(path):
        try:
            with open(path, 'rb') as file:
                data = file.read()
                inst = pickle.load(data)
        except Exception as e:
            inst = solve(e, 'load app data', easy=lambda: App(), path=path)()
    else:
        inst = App()
    inst.loadWidgets()

# e.g. A solver could search for app data if desc='load app data'
def solve(e, during, easy, **kwargs):
    class_name = e.__class__.__name__
    print(class_name + ': ' + str(e))
    print('\t during: ' + during)
    return easy
现在,因为我不想与我的应用程序的目的相左