返回介绍

建议46:使用 traceback 获取栈信息

发布于 2024-01-30 22:19:09 字数 2889 浏览 0 评论 0 收藏 0

当程序产生异常的时候,最需要面对异常的其实是开发人员,他们需要更多的异常提示的信息,以便调试程序中潜在的错误和问题。先来看一个简单的例子:

gList = ['a','b','c','d','e','f','g']
def f():
  gList[5]
  return g()
def g():
  return h()
def h():
  del gList[2]
  return i()
def i():
  gList.append('i')
  print gList[7]
if __name__ == '__main__':
  try:
    f()
  except IndexError as ex:
    print "Sorry,Exception occured,you accessed an element out of range"
    print ex

上述程序运行输出如下:

Sorry,Exception occured,you accessed an element out of range
list index out of range

信息提示有异常产生,对于用户这点还算是较为友好的,那么对于开发人员,他如何快速地知道错误发生在哪里呢?逐行检查代码吗?对于简单的程序,这也不失为一个办法,但在较为复杂的应用程序中这个方法就显得有点低效了。面对异常开发人员最希望看到的往往是异常发生时候的现场信息,traceback模块可以满足这个需求,它会输出完整的栈信息。将上述代码异常部分修改如下:

except IndexError as ex:
  print "Sorry,Exception occured,you accessed an element out of range"
  print ex
  traceback.print_exc()

程序运行会输出异常发生时候完整的栈信息,包括调用顺序、异常发生的语句、错误类型等。

Sorry,Exception occured,you accessed an element out of rangelist index out of range
Traceback (most recent call last):
  File "trace.py", line 20, in <module>
  f()
  File "trace.py", line 5, in f
  return g()
  File "trace.py", line 8, in g
  return h()
  File "trace.py", line 12, in h
  return i()
  File "trace.py", line 16, in i
  print gList[7]
IndexError: list index out of range

traceback.print_exc()方法打印出的信息包括3部分:错误类型(IndexError)、错误对应的值(list index out of range)以及具体的trace信息,包括文件名、具体的行号、函数名以及对应的源代码。Traceback模块提供了一系列方法来获取和显示异常发生时候的trace相关信息,下面列举几个常用的方法:

1)traceback.print_exception(type, value, traceback[, limit[, file]]),根据limit的设置打印栈信息,file为None的情况下定位到sys.stderr,否则则写入文件;其中type、value、traceback这3个参数对应的值可以从sys.exc_info()中获取。

2)raceback.print_exc([limit[, file]]),为print_exception()函数的缩写,不需要传入type、value、traceback这3个参数。

3)traceback.format_exc([limit]),与print_exc()类似,区别在于返回形式为字符串。

4)traceback.extract_stack([file,[, limit]]),从当前栈帧中提取trace信息。

读者可以参看Python文档获取更多关于traceback所提供的抽取、格式化或者打印程序运行时候的栈跟踪信息的方法。本质上模块trackback获取异常相关的数据都是通过sys.exc_info()函数得到的。当有异常发生的时候,该函数以元组的形式返回(type, value, traceback),其中type为异常的类型,value为异常本身,traceback为异常发生时候的调用和堆栈信息,它是一个traceback对象,对象中包含出错的行数、位置等数据。上面的例子中也可以通过如下方式输出异常发生时候的详细信息:

tb_type, tb_val, exc_tb = sys.exc_info()
for filename, linenum, funcname, source in traceback.extract_tb(exc_tb):
  print "%-23s:%s '%s' in %s()" % (filename, linenum, source, funcname)

实际上除了traceback模块本身,inspect模块也提供了获取traceback对象的接口,inspect.trace([context])可以返回当前帧对象以及异常发生时进行捕获的帧对象之间的所有栈帧记录列表,因此第一个记录代表当前调用对象,最后一个代表异常发生时候的对象。其中每一个列表元素都是一个由6个元素组成的元组:(frame对象,文件名,当前行号,函数名,源代码列表,当前行在源代码列表中的位置)。本节开头的例子在异常部分使用inspect.trace()来获取异常发生时候的堆栈信息,其部分输出结果如下:

[(<frame object at 0x022CB480>,
  'testinspect.py',
  23,
  '<module>',
  ['\t  f()\n'],
  0),
... ...]

此外如果想进一步追踪函数调用的情况,还可以通过inspect模块的inspect.stack()函数查看函数层级调用的栈相信信息。因此,当异常发生的时候,合理使用上述模块中的方法可以快速地定位程序中的问题所在。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文