Traceback的具体用法有详细说明。首先,之前做Java的时候,异常对象默认包含stacktrace相关的信息,可以通过异常对象的相关方法获取,比如printStackTrace()和getStackTrace()。可以将异常堆栈信息打印到日志中,以辅助调试或做其他事情。但是到了Python,在2.x中,异常对象可以是任何对象。经常看到很多代码直接抛出一个字符串,所以不像java那样容易拿到异常栈,因为异常对象和异常栈是分开的。大部分Python语言书籍都着重描述如何构造异常对象以及Python中raisetryexceptfinally的使用,而stacktrace这个在调试程序中起着关键作用的东西往往基本没有涉及。 python中用来处理异常栈的模块是traceback模块,它提供了print_exception、format_exception等常用工具函数来输出异常栈。deffunc(a,b):returna/bifname=='__main__':importsysimporttracebacktry:func(1,0)除了Exceptionase:print"printexc"traceback.print_exc(file=sys.stdout)输出:打印excTraceback(最后一次调用):文件“./teststacktrace.py”,第7行,在func(1,0)文件“./teststacktrace.py”,第2行,在funcreturna/b其实traceback.print_exc()函数只是traceback.print_exception()函数的简写形式,他们通过sys.exc_info()函数获取异常相关的数据。deffunc(a,b):returna/bifname=='__main__':importsysimporttracebacktry:func(1,0)exceptExceptionase:print"print_exception()"exc_type,exc_value,exc_tb=sys.exc_info()print'exc类型为:',exc_typeprint'exc值为:',exc_valueprint'exctb为:',exc_tbtraceback.print_exception(exc_type,exc_value,exc_tb)输出结果:print_exception()theexc类型是:exc值是:整数除法或除以零exctb是:Traceback(最近调用最后):文件“./teststacktrace.py”,第7行,在func(1,0)File"./teststacktrace.py",第2行,在funcreturna/bZeroDivisionError:integerdivisionormodulobyzerosys.exc_info()返回一个元组,其中第一个元素,exc_type是异常的对象类型,exc_value是异常的值,exc_tb是一个traceback对象,包含了行数、出错位置等数据。然后使用print_exception函数将这些异常数据整理输出。traceback模块提供了extract_tb函数来更详细的解释traceback对象包含的数据:deffunc(a,b):returna/bifname=='__main__':importsysimporttracebacktry:func(1,0)except:_,_,exc_tb=sys.exc_info()forfilename,linenum,funcname,sourceintraceback.extract_tb(exc_tb):print"%-23s:%s'%s'in%s()"%(文件名、linenum、源、funcname)输出:samchimac:tracebacktestsamchi$python./teststacktrace.py./teststacktrace.py:7'func(1,0)'in()./teststacktrace.py:2'returna/b'infunc()使用cgitb来简化异常调试。如果你喜欢以基于日志的方式进行调试,你可能经常会做这样的事情。在日志中发现异常后,由于信息不足,会去额外的添加一些debuglog来输出相关变量的值。调试后,删除这些调试日志。其实大可不必这么麻烦。Python库中提供了cgitb模块来帮助完成这些事情。它可以输出异常上下文中所有相关变量的信息,这样就不用每次都手动添加debuglog了。cgitb的使用简单到超乎想象:deffunc(a,b):returna/bifname=='__main__':importcgitbcgitb.enable(format='text')importsysimporttracebackfunc(1,0)会跑起来详细数据:Python脚本中出现问题。以下是导致错误的函数调用序列,按它们发生的顺序排列。/Users/samchi/Documents/workspace/tracebacktest/teststacktrace.pyin()4importcgitb5cgitb.enable(format='text')6importsys7importtraceback8func(1,0)func=/Users/samchi/Documents/workspace/tracebacktest/teststacktrace.pyinfunc(a=1,b=0)2returna/b3if__name__=='__main__':4importcgitb5cgitb.enable(format='text')6importsysa=1b=0不用去log.debug("a=%d"%a),个人感觉cgitb线上环境不太适合用,适合开发时调试过程,非常方便。也许你会问,为什么cgitb这么屌?能得到这么详细的错误信息吗?其实它的工作原理和用法一样简单,只是覆盖了默认的sys.excepthook函数,sys.excepthook是一个默认的全局异常拦截器,你可以自己修改试试:deffunc(a,b):returna/bdefmy_exception_handler(exc_type,exc_value,exc_tb):print"icatchedtheexception:",exc_typewhileexc_tb:print"thelineno:",exc_tb.tb_linenoprint"theframelocals:",exc_tb.tb_frame.f_localsexc_tb=复制代码exc_tb.tb_nextifname=='__main__':importsyssys.excepthook=my_exception_handlerimporttracebackfunc(1,0)输出:我捕获到异常:行号:14theframelocals:{'my_exception_handler':,'__builtins__':,'__file__':'./teststacktrace.py','traceback':,'__package__':None,'sys':,'func':<函数ionfuncat0x100e04320>,'__name__':'__main__','__doc__':None}thelineno:2theframelocals:{'a':1,'b':0}只是从stackframe对象中获取的相关变量值框对象有很多神奇的属性,就不一一探究了。使用日志记录模块记录异常。在使用Java的时候,使用log4j记录异常是非常简单的。只需将Exception对象传递给log.error方法,但它在Python中不起作用。如果直接将异常对象传递给log.error,那么日志中只会出现一行异常对象值。Python中记录Log的正确方式应该是这样的:logging.exception(ex)logging.error(ex,exc_info=1)#指定输出stacktrace,logging.exception内部也包含一层这个方法logging.critical(ex,exc_info=1)#更严重的错误级别