Python代码调试之异常回溯

2017-04-10 董付国 Python小屋 Python小屋

当发生异常时,Python会回溯异常,给出大量的提示,可能会给程序员的定位和纠错带来一定的困难,这时可以使用sys模块的exc_info()函数来回溯最近一次异常。

sys.exc_info( )的返回值tuple是一个三元组(type,  value,  traceback),其中:

  • type —— 异常的类型

  • value —— 异常的信息或者参数

  • traceback —— 包含调用栈信息的对象


例如:

>>> 1/0

Traceback (most recent call last):

  File "<pyshell#25>", line 1, in <module>

    1/0

ZeroDivisionError: integer division or modulo by zero


>>> import sys

>>> try:

1/0

except:

r = sys.exc_info()

print(r)


(<class 'ZeroDivisionError'>, ZeroDivisionError('division by zero',), <traceback object at 0x000000000375C788>)


sys.exc_info()可以直接定位最终引发异常的原因,结果也比较简洁,但是缺点是难以直接确定引发异常的代码位置。假设有如下函数定义:

>>> def A():1/0

>>> def B():A()

>>> def C():B()


直接调用函数,抛出异常:

>>> C()

Traceback (most recent call last):

  File "<pyshell#35>", line 1, in <module>

    C()

  File "<pyshell#34>", line 2, in C

    B()

  File "<pyshell#31>", line 2, in B

    A()

  File "<pyshell#28>", line 2, in A

    1/0

ZeroDivisionError: integer division or modulo by zero


使用sys.exc_info()查看异常信息时并不是非常直观:

>>> try:

       C()

except:

       r = sys.exc_info()

       print(r)

(<type 'exceptions.ZeroDivisionError'>, ZeroDivisionError('integer division or modulo by zero',), <traceback object at 0x0134C990>)


如果需要的话,可以使用traceback模块来查看详细信息:

>>> import traceback

>>> import sys

>>> def A():1/0

>>> def B():A()

>>> def C():B()

>>> try:

    C()

except:

    excType, excValue, excTraceback = sys.exc_info()

    traceback.print_exception(excType, excValue,

                              excTraceback, limit=3)

    print(excValue)

    traceback.print_tb(excTraceback)


Traceback (most recent call last):

  File "<pyshell#44>", line 2, in <module>

  File "<pyshell#42>", line 1, in C

  File "<pyshell#40>", line 1, in B

ZeroDivisionError: division by zero

division by zero

  File "<pyshell#44>", line 2, in <module>

  File "<pyshell#42>", line 1, in C

  File "<pyshell#40>", line 1, in B

  File "<pyshell#38>", line 1, in A