如何获取发生python异常的实际行号?

Saq*_*Ali 1 python django exception-handling

我的文件中有以下 python 装饰器 decorators.py

def catch_exceptions(function):                                           #Line #1
    @wraps(function)                                                      #Line #2
    def decorator(*args, **kwargs):                                       #Line #3
        try:                                                              #Line #4
            return function(*args, **kwargs)                              #Line #5
        except Exception as e:                                            #Line #6
            exc_type, exc_obj, exc_tb = sys.exc_info()                    #Line #7
            fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]  #Line #8
            print "E=%s, F=%s, L=%s" % (str(e), fname, exc_tb.tb_lineno)  #Line #9
    return decorator                                                      #Line #10
Run Code Online (Sandbox Code Playgroud)

在另一个文件中my_file.py,我使用这样的catch_exceptions装饰器:

from decorators import catch_exceptions                                   #Line #1
@catch_exceptions                                                         #Line #2
def my_method()                                                           #Line #3
    print (10/0 - 5/0)                                                    #Line #4
Run Code Online (Sandbox Code Playgroud)

当我运行它时,我得到以下输出:

E=integer division or modulo by zero, F=decorators.py, L=5
Run Code Online (Sandbox Code Playgroud)

而不是将异常位置报告为decorators.py第 5 行,如何让它报告最初发生异常的位置的实际文件和行号?那将是my_file.py.

vis*_*ell 6

如果你想按照你所描述的那样做

\n\n
from functools import wraps\nimport sys, os, traceback\n\ndef catch_exceptions(function):                                           \n    @wraps(function)                                                     \n    def decorator(*args, **kwargs):                                      \n        try:                                                              \n            return function(*args, **kwargs)                              \n        except Exception as e:                                            \n            exc_type, exc_obj, exc_tb = sys.exc_info()\n            print "E=%s, F=%s, L=%s" % (str(e), traceback.extract_tb(exc_tb)[-1][0], traceback.extract_tb(exc_tb)[-1][1]) ) \n    return decorator\n
Run Code Online (Sandbox Code Playgroud)\n\n

但这仍然是traceback您需要知道的。

\n\n

我相信filename那是印刷也是一个错误。

\n\n

exc_tb实际物体也是如此traceback。提取它的数据就extract_tb()可以了

\n\n
\n

返回从回溯对象 tb 中提取的最多限制 \xe2\x80\x9cpre-processed\xe2\x80\x9d 堆栈跟踪条目的列表。它对于堆栈跟踪的替代格式很有用。如果省略 limit 或None,则提取所有条目。\xe2\x80\x9cpre-processed\xe2\x80\x9d 堆栈跟踪条目是一个 4 元组(文件名、行号、函数名*、文本),表示通常为堆栈跟踪打印的信息。

\n
\n\n

因此,倒数第二个元素traceback.extract_tb(exc_tb)将是装饰器中引发的异常,最后一个元素将在您的函数中。所以最后一个index( -1)就是我们所需要的。然后traceback.extract_tb(exc_tb)[-1][0]是(我想)您想要的文件的文件名,而不是decorators.pytraceback.extract_tb(exc_tb)[-1][1]将是引发异常时的行。

\n


Bre*_*bel 5

您可能需要查看traceback模块

import traceback

try:
    function_that_raises_exception()
except Exception:
    traceback.print_exc()
Run Code Online (Sandbox Code Playgroud)

它将打印整个堆栈跟踪。