Some_function()在执行时引发异常,因此程序跳转到异常:

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

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


你通常不应该用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

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


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

发生错误的事实 发生错误的细节(错误隐藏反模式)

因此,只要您注意不做这些事情,就可以捕获泛型异常。例如,你可以用另一种方式向用户提供异常信息,比如:

在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

Make sure message is brought to the attention of the user in a hard-to-miss way! Printing it, as shown above, may not be enough if the message is buried in lots of other messages. Failing to get the users attention is tantamount to swallowing all exceptions, and if there's one impression you should have come away with after reading the answers on this page, it's that this is not a good thing. Ending the except block with a raise statement will remedy the problem by transparently reraising the exception that was caught.

上述用法和使用just except: without any argument的区别有两个方面:

裸except:不提供要检查的异常对象 异常SystemExit, KeyboardInterrupt和GeneratorExit不会被上面的代码捕获,这通常是你想要的。参见异常层次结构。

如果你也想要与你没有捕获异常时得到的stacktrace相同,你可以像这样得到(仍然在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()

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


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

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

引发后,原始异常继续向上传播调用堆栈。(注意可能的陷阱)如果你引发新的异常,它会携带新的(更短的)堆栈跟踪。

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    

注意traceback如何不包括第9行中的compute()函数,这是原始异常e的起源。


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


除非某个函数是一个编码非常糟糕的遗留函数,否则你不应该需要你所要求的。

使用多个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

这可以在类方法或带有装饰器的独立函数上调用:

@general_function_handler

完整的例子请参阅我的博客:http://ryaneirwin.wordpress.com/2014/05/31/python-decorators-and-exception-handling/


你的问题是:“我如何才能确切地看到someFunction()中发生了什么导致异常发生?”

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

最简单的方法是使用调试器,该调试器可以在未捕获异常发生的地方停止,最好不要退出,以便您可以检查变量。例如,Eclipse开源IDE中的PyDev可以做到这一点。要在Eclipse中启用该功能,请打开Debug透视图,在Run菜单中选择管理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

目前,由于我不想考虑应用程序的用途,所以我没有添加任何复杂的解决方案。但在未来,当我了解更多可能的解决方案时(因为应用程序设计得更多),我可以添加一个以during为索引的解决方案字典。

在这个例子中,一种解决方案可能是寻找存储在其他地方的应用程序数据,比如‘app.p’文件被错误删除了。

现在,因为编写异常处理程序不是一个明智的想法(我们还不知道解决它的最佳方法,因为应用程序的设计将不断发展),我们只是返回简单的修复,这就像我们第一次运行应用程序一样(在这种情况下)。


大多数答案指向except(…)as(…):语法(正确),但同时没有人想谈论房间里的大象,而大象是sys.exc_info()函数。 来自sys模块的文档(重点是我的):

This function returns a tuple of three values that give information about the exception that is currently being handled. (…) If no exception is being handled anywhere on the stack, a tuple containing three None values is returned. Otherwise, the values returned are (type, value, traceback). Their meaning is: type gets the type of the exception being handled (a subclass of BaseException); value gets the exception instance (an instance of the exception type); traceback gets a traceback object (see the Reference Manual) which encapsulates the call stack at the point where the exception originally occurred.

我认为sys.exc_info()可以被视为对原始问题“我如何知道发生了什么类型的异常?”的最直接答案。


这些答案很适合调试,但对于以编程方式测试异常,isinstance(e, SomeException)可能很方便,因为它也测试SomeException的子类,因此您可以创建应用于异常层次结构的功能。


使用下面的异常类型和异常文本

import sys
print(str(sys.exc_info()[0]).split(' ')[1].strip('>').strip("'")+"-"+(str(sys.exc_info()[1])))

如果你只想要异常类型:使用——>

import sys
print(str(sys.exc_info()[0]).split(' ')[1].strip('>').strip("'"))

由于Rajeshwar


希望这对你有帮助

import sys
varExcepHandling, varExcepHandlingZer = 2, 0
try:
  print(varExcepHandling/varExcepHandlingZer)
except Exception as ex: 
  print(sys.exc_info())

'sys.exc_info()'将返回一个元组,如果你只想要异常类名,请使用'sys.exc_info()[0]'

注意:-如果你想看到所有的异常类,只需写入dir(__builtin__)


使用类型class和as语句

try:#code
except Exception as e:
     m=type(e)
     #m is the class of the exception
     strm=str(m)
     #strm is the string of m