简体   繁体   English

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

[英]How to get actual line number of where python exception occurred?

I have the following python decorator in my file decorators.py我的文件decorators.py有以下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

In another file my_file.py , I use the catch_exceptions decorator like this:在另一个文件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

When I run it, I get the following output:当我运行它时,我得到以下输出:

E=integer division or modulo by zero, F=decorators.py, L=5

Instead of it reporting the exception location as decorators.py , line #5, How can I get it to report the actual file and line number of where the exception originally occurred?而不是将异常位置报告为decorators.py ,第 5 行,如何让它报告最初发生异常的实际文件和行号? That would be line #4 in my_file.py .那将是my_file.py第 4 行。

You may want to look into the traceback module您可能需要查看traceback模块

import traceback

try:
    function_that_raises_exception()
except Exception:
    traceback.print_exc()

It will print the entire stack trace.它将打印整个堆栈跟踪。

If you want to do it as you described then如果你想按照你描述的那样做

from functools import wraps
import sys, os, traceback

def catch_exceptions(function):                                           
    @wraps(function)                                                     
    def decorator(*args, **kwargs):                                      
        try:                                                              
            return function(*args, **kwargs)                              
        except Exception as e:                                            
            exc_type, exc_obj, exc_tb = sys.exc_info()
            print "E=%s, F=%s, L=%s" % (str(e), traceback.extract_tb(exc_tb)[-1][0], traceback.extract_tb(exc_tb)[-1][1]) ) 
    return decorator

But it's still traceback that you need to know.但它仍然是你需要知道的traceback

I believe that filename that was printing was also a mistake.我相信正在打印的filename也是一个错误。

So exc_tb is actual traceback object.所以exc_tb是实际的traceback对象。 And extracting it's data is made by extract_tb() it will do并且提取它的数据是由extract_tb()完成的

Return a list of up to limit “pre-processed” stack trace entries extracted from the traceback object tb.返回从回溯对象 tb 中提取的最多限制“预处理”堆栈跟踪条目的列表。 It is useful for alternate formatting of stack traces.它对于堆栈跟踪的替代格式很有用。 If limit is omitted or None , all entries are extracted.如果省略 limit 或None ,则提取所有条目。 A “pre-processed” stack trace entry is a 4-tuple (filename, line number, function name*, text) representing the information that is usually printed for a stack trace. “预处理”堆栈跟踪条目是一个 4 元组(文件名、行号、函数名*、文本),表示通常为堆栈跟踪打印的信息。

So the second last element of traceback.extract_tb(exc_tb) would be exception that is raised in decorator, and the last would be in your function.因此, traceback.extract_tb(exc_tb)倒数第二个元素将是在装饰器中引发的异常,而最后一个元素将在您的函数中。 So the last index( -1 ) is what we need.所以最后一个索引( -1 )就是我们需要的。 Then traceback.extract_tb(exc_tb)[-1][0] would be filename of (I suppose) your desired file, not decorators.py and traceback.extract_tb(exc_tb)[-1][1] would be the line when the exception was fired.然后traceback.extract_tb(exc_tb)[-1][0]将是(我想)你想要的文件的文件名,而不是decorators.pytraceback.extract_tb(exc_tb)[-1][1]将是当异常被解雇。

We can get the line number by splitting the string state of the traceback.format_exc() .我们可以通过拆分traceback.format_exc()的字符串状态来获取行号。 Please have a look at my answer at the following question, I have added sample code there.请看看我对以下问题的回答,我在那里添加了示例代码。

enter link description here在此处输入链接描述

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM