class ZeroDivZeroError(ZeroDivisionError):
def __init__(self, value):
self.value = value
def __str__(self):
return repr(self)
def __repr__(self):
return self.value
try:
# do something and find 0 / 0
raise ZeroDivZeroError('hahajun')
except ZeroDivZeroError as err:
print 'except info %s' % err
自定义异常应该直接继承自Exception类或其子类,而不要继承自BaseException.
3. Stack Tracepython执行过程中发生异常,会告诉我们到底哪里出现问题和什么问题。这两种类型的错误信息分别为stack trace和 exception,在程序中分别用traceback object和异常对象表示。
Traceback (most recent call last): File "D:\My Folders\Cnblogs\Alpha Panda\Main.py", line 270, in <module> 1 / 0 ZeroDivisionError: integer division or modulo by zero
上面的错误信息包含错误发生时当前的堆栈信息(stack trace, 前三行)和异常信息(exception,最后一行),分别存放在traceback objects和抛出的异常对象中。
异常对象及异常信息前面已经介绍过,接下来我们在看一下异常发生时,stack trace的处理。
Traceback objects represent a stack trace of an exception. A traceback object is created when an exception occurs.
这时有两种情况:
异常被try...except捕获
没有被捕获或者干脆没有处理
正常的代码执行过程,可以使用traceback.print_stack()输出当前调用过程的堆栈信息。
3.1 捕获异常对于第一种情况可以使用下面两种方式获取stack trace信息:
trace_str = traceback.format_exc()
或者从sys.exc_info()中获取捕获的异常对象等的信息,然后格式化成trace信息。def get_trace_str(self):
"""
从当前栈帧或者之前的栈帧中获取被except捕获的异常信息;
没有被try except捕获的异常会直接传递给sys.excepthook
"""
t, v, tb = sys.exc_info()
trace_info_list = traceback.format_exception(t, v, tb)
trace_str = ' '.join(trace_info_list)
至于抛出的包含异常信息的异常对象则可以在try...except结构中的except Exception class as e中获取。
3.2 未捕获异常第二种情况,如果异常没有被处理或者未被捕获则会在程序推出前调用sys.excepthook将traceback和异常信息输出到sys.stderr。
def except_hook_func(tp, val, tb): trace_info_list = traceback.format_exception(tp, val, tb) trace_str = ' '.join(trace_info_list) print 'sys.excepthook' print trace_str sys.excepthook = except_hook_func
上面自定义except hook函数来取代sys.excepthook函数。在hook函数中根据异常类型tp、异常值和traceback对象tb获取stack trace。这种情况下不能从sys.exc_info中获取异常信息。
3.3 测试def except_hook_func(tp, val, tb): trace_info_list = traceback.format_exception(tp, val, tb) trace_str = ' '.join(trace_info_list) print 'sys.excepthook' print trace_str sys.excepthook = except_hook_func try: 1 / 0 except TypeError as e: res = traceback.format_exc() print "try...except" print str(e.message) print res
走的是sys.excepthook处理流程结果:
sys.excepthook Traceback (most recent call last): File "D:\My Folders\Cnblogs\Alpha Panda\Main.py", line 259, in <module> 1 / 0 ZeroDivisionError: integer division or modulo by zero
将except TypeError as e 改为 except ZeroDivisionError as e,则走的是try...except捕获异常流程,结果如下:
try...except integer division or modulo by zero Traceback (most recent call last): File "D:\My Folders\Cnblogs\Alpha Panda\Main.py", line 259, in <module> 1 / 0 ZeroDivisionError: integer division or modulo by zero
4. 异常信息收集讲了这么多,我们看一下如何实现一个程序中trace信息的收集。
class TracebackMgr(object):
def _get_format_trace_str(self, t, v, tb):
_trace = traceback.format_exception(t, v, tb)
return ' '.join(_trace)