gList=['a','b','b','c','e']
def f():
gList[5]
return g()
def g():
return h()
def i():
gList.append('i')
print(gList[6])
if __name__=='__main__':
try:
f()
except IndexError as ex:
print ("sorry")
print(ex)
sorry list index out of range
程序运行输出如上结果。
信息提示有异常产生,对于用户这点还算是较为友好的,那么对于开发人员,他如何快速地知道错误发生在哪里呢? 逐行检查代码吗?对于简单的程序,这也不失为一个办法,但在较为复杂的应用程序中这个方法就显得有点低效了。
面对异常开发人员最希望看到的往往是异常发生时候的现场信息, tmceback 模块可以满足这个需求,它会输出完整的栈信息。
将上述代码异常部分修改如下:
gList=['a','b','b','c','e']
def f():
gList[5]
return g()
def g():
return h()
def i():
gList.append('i')
print(gList[6])
# if __name__=='__main__':
# try:
# f()
# except IndexError as ex:
# print ("sorry")
# print(ex)
# import traceback
# traceback.print_exc()
程序运行会输出异常发生时候完整的栈信息,包括调用顺序、异常发生的语句、错误类型等。
traceback.print_exc() 方法打印出的信息包括3部分:
- 错误类型(IndexError)
- 错误对应 的值(list index out of range)
- 具体的
trace信息,包括文件名、具体的行号、函数名以及 对应的源代码。
Traceback 模块获取栈信息的方法
Traceback 模块提供了一系列方法来获取和显示异常发生时候的 trace 相关信息,下面列举几个常用的方法:
traceback.print_exception{iype, value, traceback[, limit[, file]]), 根据limit的设置打印找信息.file为None的情况下定位到sys.stderr, 否则则写入文件;其中type、value、traceback这3个参数对应的值可以从sys.exc_info()中获取。raceback,print_cxc([limitl, file]]),为print_exception()函数的缩写, 不需要传入type,value、traceback这 3 个参数。traceback_format_exc([Hmit]), 与print_exc()类似,区别在于返回形式为字符串。traceback.extract_stack([file,[, limit]]), 从当前栈中提取trace信息。
读者可以参看Python文档获取更多关于 traceback 所提供的抽取、 格式化或者打印程序运行时候的栈跟踪信息的方法。
本质上模块 trackback 获取异常相关的数据都是通过 sys.exc_info() 函数得到的。 当有异常发生的时候,该函数以元组的形式返回( type , value , traceback ), 其中 type 为异常的类型,value 为异常本身,tracebaclc 为异常发生时候的调用和堆栈信息, 它是一个 traceback 对象,对象中包含出错的行数、位置等数据。
上面的例子中也可以通过如下方式输出异常发生时候的详细信息:
# import sys
# tb_type,tb_bal,exc_tb=sys.exc_info()
# for f,l,fc,su in traceback.extract_tb(exc_tb):
# print("%-23s :%s '%s' in %s ()" %(f,l,fc,su))
实际上除了 traceback 模块本身,inspect 模块也提供了获取 traceback 对象的接口, inspect.trace([context]) 可以返回当前帧对象以及异常发生时进行捕获的帧对象之间的所有栈帧记录列表, 因此第一个记录代表当前调用对象,最后一个代表异常发生时候的对象。 其中每一个列表元素都是一个由6个元素组成的元组: ( frame 对象,文件名,当前行号,函数名,源代码列表,当前行在源代码列表中的位置)。 本节开头的例子在异常部分使用 inspect.trace() 来获取异常发生时候的堆栈信息,其部分输出结果如下:
[(frame object at Ox022CB480>,
testinspect.py,
23,
<module>',
['\t f 0\n'] r
0) ,]此外如果想进一步追踪函数调用的情况, 还可以通过 inspect 模块的 inspect.stack() 函数査看函数层级调用的栈相信信息。 因此,当异常发生的时候,合理使用上述模块中的方法可以快速地定位程序中的问题所在。