【问题标题】:Python exception handling - line numberPython异常处理——行号
【发布时间】:2013-01-09 06:16:51
【问题描述】:

我正在使用 python 来评估一些测量数据。由于许多可能的结果,很难处理或可能的组合。有时在评估过程中会发生错误。这通常是索引错误,因为我超出了测量数据的范围。

很难找出问题发生在代码中的哪个位置。如果我知道在哪一行引发了错误,那将有很大帮助。如果我使用以下代码:

try:
    result = evaluateData(data)
except Exception, err:
    print ("Error: %s.\n" % str(err))

不幸的是,这只告诉我存在索引错误。我想了解有关异常的更多详细信息(代码行、变量等)以了解发生了什么。有可能吗?

谢谢。

【问题讨论】:

标签: python exception indexing


【解决方案1】:

要简单地获取行号,您可以使用sys,如果您想要更多,请尝试traceback 模块。

import sys    
try:
    [][2]
except IndexError:
    print("Error on line {}".format(sys.exc_info()[-1].tb_lineno))

打印

Error on line 3

Example from the traceback module documentation:

import sys, traceback

def lumberjack():
    bright_side_of_death()

def bright_side_of_death():
    return tuple()[0]

try:
    lumberjack()
except IndexError:
    exc_type, exc_value, exc_traceback = sys.exc_info()
    print "*** print_tb:"
    traceback.print_tb(exc_traceback, limit=1, file=sys.stdout)
    print "*** print_exception:"
    traceback.print_exception(exc_type, exc_value, exc_traceback,
                              limit=2, file=sys.stdout)
    print "*** print_exc:"
    traceback.print_exc()
    print "*** format_exc, first and last line:"
    formatted_lines = traceback.format_exc().splitlines()
    print formatted_lines[0]
    print formatted_lines[-1]
    print "*** format_exception:"
    print repr(traceback.format_exception(exc_type, exc_value,
                                          exc_traceback))
    print "*** extract_tb:"
    print repr(traceback.extract_tb(exc_traceback))
    print "*** format_tb:"
    print repr(traceback.format_tb(exc_traceback))
    print "*** tb_lineno:", exc_traceback.tb_lineno

【讨论】:

    【解决方案2】:

    解决方法、打印文件名、行号、行本身和异常描述:

    import linecache
    import sys
    
    def PrintException():
        exc_type, exc_obj, tb = sys.exc_info()
        f = tb.tb_frame
        lineno = tb.tb_lineno
        filename = f.f_code.co_filename
        linecache.checkcache(filename)
        line = linecache.getline(filename, lineno, f.f_globals)
        print 'EXCEPTION IN ({}, LINE {} "{}"): {}'.format(filename, lineno, line.strip(), exc_obj)
    
    
    try:
        print 1/0
    except:
        PrintException()
    

    输出:

    EXCEPTION IN (D:/Projects/delme3.py, LINE 15 "print 1/0"): integer division or modulo by zero
    

    【讨论】:

    • 对于我的 python 3.6.5,我需要在最后一行添加括号,打印: print('EXCEPTION IN ({}, LINE {} "{}"): {}'.format(filename , lineno, line.strip(), exc_obj))
    • 这将为您提供有关堆栈跟踪中第一个文件的信息。但大多数时候你想要最后一个,因为那是实际发生错误的地方。
    • 我们如何获取最后一个? @reubano
    • @alper 见my answer
    【解决方案3】:

    最简单的方法就是使用:

    import traceback
    try:
        <blah>
    except IndexError:
        traceback.print_exc()
    

    或者如果使用日志记录:

    import logging
    try:
        <blah>
    except IndexError as e:
        logging.exception(e)
    

    【讨论】:

      【解决方案4】:

      我使用简单而强大的traceback

      import traceback
      
      try:
          raise ValueError()
      except:
          print(traceback.format_exc())
      

      输出:

      Traceback (most recent call last):
        File "catch.py", line 4, in <module>
          raise ValueError()
      ValueError
      

      【讨论】:

      • 这是最好的答案。当错误在函数内部时,其他人没有正确显示错误行
      【解决方案5】:

      我建议使用 python 日志库,它有两个有用的方法可能会在这种情况下有所帮助。

      1. logging.findCaller()

        • findCaller(stack_info=False) - 只报告导致异常的前一个调用者的行号
        • findCaller(stack_info=True) - 报告导致引发异常的前一个调用者的行号和堆栈
      2. logging.logException()

        • 报告引发异常的 try/except 块中的行和堆栈

      欲了解更多信息,请查看 api https://docs.python.org/3/library/logging.html

      【讨论】:

        【解决方案6】:

        我一直用这个sn-p

        import sys, os
        
        try:
            raise NotImplementedError("No error")
        except Exception as e:
            exc_type, exc_obj, exc_tb = sys.exc_info()
            fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
            print(exc_type, fname, exc_tb.tb_lineno)
        

        对于不同的观点和可能的问题,您可以参考When I catch an exception, how do I get the type, file, and line number?

        【讨论】:

          【解决方案7】:

          为您提供调用堆栈中最后一项的文件、行号和异常

          from sys import exc_info
          from traceback import format_exception
          
          
          def print_exception():
              etype, value, tb = exc_info()
              info, error = format_exception(etype, value, tb)[-2:]
              print(f'Exception in:\n{info}\n{error}')
          
          try:
              1 / 0
          except:
              print_exception()
          

          打印

          Exception in:
             File "file.py", line 12, in <module>
              1 / 0
          
          ZeroDivisionError: division by zero
          
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2010-12-26
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2010-10-15
            • 2022-10-14
            相关资源
            最近更新 更多