def handle_one_exception(self):
"""
从当前栈帧或者之前的栈帧中获取被except捕获的异常信息;
没有被try except捕获的异常会自动使用handle_traceback进行收集
"""
t, v, tb = sys.exc_info()
self.handle_traceback(t, v, tb, False)
def handle_traceback(self, t, v, tb, is_hook = True):
"""
将此函数替换sys.excepthook以能够自动收集没有被try...except捕获的异常,
使用try except处理的异常需要手动调用上面的函数handle_one_exception才能够收集
"""
trace_str = self._get_format_trace_str(t, v, tb)
self.record_trace(trace_str, is_hook)
# do something else
def record_trace(self, trace_str, is_hook):
# Do somethind
print 'is_hook: %s' % is_hook
print trace_str
其用法很简单:
trace_mgr = TracebackMgr() sys.excepthook = trace_mgr.handle_traceback try: 1 / 0 except Exception as e: trace_mgr.handle_one_exception() # process trace 1 / '0'
结果用两种方式收集到两个trace信息:
is_hook: False Traceback (most recent call last): File "D:\My Folders\Cnblogs\Alpha Panda\Main.py", line 299, in <module> 1 / 0 ZeroDivisionError: integer division or modulo by zero is_hook: True Traceback (most recent call last): File "D:\My Folders\Cnblogs\Alpha Panda\Main.py", line 304, in <module> 1 / '0' TypeError: unsupported operand type(s) for /: 'int' and 'str'
可以将标准的输入和输出重定向,将打印日志和错误信息输入到文件中:
class Dumpfile(object): @staticmethod def write(str_info): with open('./dump_file.txt', 'a+') as fobj: fobj.write(str_info) def flush(self): self.write('') sys.stdout = sys.stderr = Dumpfile()
trace的收集主要用到两点:如何捕获异常和两种情况下异常信息的收集,前面都介绍过。
5. 总结python 异常处理:
使用对象来表示异常错误信息,每种异常均有一种对应的类,BaseException为所有表示异常处理类的基类。
程序执行过程中抛出的异常会匹配该对象对应的异常类和其所有的基类。
可以从内置类型的异常类派生出自定义的异常类。
被捕获的异常可以再次被抛出。
可以的话尽量使用内置的替代方案,如if getattr(obj, attr_name, None),或者with结构等。
sys.exc_info()保存当前栈帧或者之前的栈帧中获取被try, except捕获的异常信息。
未处理的异常导致程序终止前会被sys.excpethook处理,可以自定义定义sys.excpethook。
异常的陷阱:
正确的异常处理能让代码有更好的鲁棒性,但是错误的使用异常会过犹不及。
捕获异常却忽略掉或者错误的处理是不可取的。滥用异常处理不仅达不到提高系统稳定性的效果,还会隐藏掉引起错误的诱因,导致排查问题的难度增加。
因此比如何捕获异常更重要的是,异常发生时应当如何处理。