【问题标题】:Locating the line number where an exception occurs in python code定位python代码中发生异常的行号
【发布时间】:2011-08-05 19:40:58
【问题描述】:

我有一个类似这样的代码:

try:
  if x:
      statement1
      statement2
      statement3
  elif y:
      statement4
      statement5
      statement6
  else:
      raise

except:
      statement7

这里,我确定异常发生在If x:块中,但是我想知道异常发生在If x:块的哪个语句中。有没有办法获取发生异常的行号?

问候,

【问题讨论】:

  • 你没有提到你为什么想要这个。用于调试问题?所以 statement7 可以根据引发异常的位置做一些不同的事情吗?你能告诉我们更多吗?
  • 在我的代码中,语句 1 或语句 2 中不应发生异常。如果发生,则语句 1 或 2 中的任何一个都有问题。在 statement3 中包含它是可以接受的。这就是为什么我想知道哪一行有异常。
  • 但是您将如何处理这些信息?你需要它一次来修复程序,还是在运行时需要它?
  • 我需要它一次来修复故障线路。现在我找到了故障线路,谢谢大家!

标签: python exception


【解决方案1】:

这个呢:

try:
  if x:
      print 'before statement 1'
      statement1
      print 'before statement 2' #ecc. ecc.
      statement2
      statement3
  elif y:
      statement4
      statement5
      statement6
  else:
      raise

except:
      statement7

这是简单的解决方法,但我建议使用调试器

或者更好的是,使用 sys 模块:D

try:
      if x:
          print 'before statement 1'
          statement1
          print 'before statement 2' #ecc. ecc.
          statement2
          statement3
      elif y:
          statement4
          statement5
          statement6
      else:
          raise
except:
    print sys.exc_traceback.tb_lineno 
    #this is the line number, but there are also other infos

【讨论】:

【解决方案2】:

我相信这里建议您更紧密地管理try/except 块的几个答案是您正在寻找的答案。那是风格的东西,而不是图书馆的东西。

但是,有时我们会发现它不是一种风格,而您确实确实需要行号来执行其他一些程序化操作。如果这就是您要问的,您应该考虑traceback 模块。您可以提取有关最近异常的所有信息。 tb_lineno 函数将返回导致异常的行号。

>>> import traceback
>>> dir(traceback)
['__all__', '__builtins__', '__doc__', '__file__', '__name__', '__package__', '_format_final_exc_line', '_print', '_some_str', 'extract_stack', 'extract_tb', 'format_exc', 'format_exception', 'format_exception_only', 'format_list', 'format_stack', 'format_tb', 'linecache', 'print_exc', 'print_exception', 'print_last', 'print_list', 'print_stack', 'print_tb', 'sys', 'tb_lineno', 'types']
>>> help(traceback.tb_lineno)
Help on function tb_lineno in module traceback:

tb_lineno(tb)
Calculate correct line number of traceback given in tb.
Obsolete in 2.3

较新版本的回溯管道修复了 2.3 之前的问题,允许下面的代码按预期工作:(这是“正确的方式”)

import traceback
import sys

try:
    raise Exception("foo")
except:
    for frame in traceback.extract_tb(sys.exc_info()[2]):
        fname,lineno,fn,text = frame
        print "Error in %s on line %d" % (fname, lineno)

【讨论】:

  • 谢谢,我按照你说的尝试了,但我得到了以下信息:行号发生异常:
  • tb_lineno 是一个函数,而不是一个属性。它将回溯作为参数。我编辑了帖子以更清楚。尝试“print traceback.tb_lineno(sys.exc_info()[2])”——确保添加括号。
【解决方案3】:

您应该在调试器中运行您的程序,例如pdb。这将允许您正常运行代码,然后在发生此类意外情况时检查环境。

给定一个名为“main.py”的脚本,像这样运行它:

python -m pdb main.py

然后,当您的程序启动时,它将在调试器中启动。键入 c 以继续直到下一个断点(或崩溃)。然后,您可以通过执行print spam.eggs 之类的操作来检查环境。你也可以通过pdb.set_trace()设置断点(我通常是import pdb; pdb.set_trace())。

此外,“语句 3”引发异常是什么意思?你期待例外吗?如果是这样,最好在该语句周围写一个 try/except 块,以便程序可以继续。

【讨论】:

  • 史诗!与 Django 一起工作非常棒,例如。 python -m pdb manage.py syncdb --settings=settings_developmentpython -m pdb manage.py runserver --settings=settings_development.
【解决方案4】:

我之前做过以下事情:

try:
    doing = "statement1"
    statement1
    doing = "statement2"
    statement2
    doing = "statement3"
    statement3
    doing = "statement4"
    statement4

 except:
    print "exception occurred doing ", doing

打印检查点的优势是没有日志输出,除非 实际上有一个例外。

【讨论】:

    【解决方案5】:

    以上面的 JJ 为基础..

    使用系统错误而不是语句的优点是它们记录了更具体的信息,这将有助于以后的调试(相信我,我得到了很多)

    例如。我将它们记录到一个文本文件中,所以当我的程序在服务器上自动运行一夜之后,我可以检索任何问题,并且有足够的信息来加快修复!

    更多信息...Traceback & Sys

    import traceback
    import sys
    
    try:
        print 1/0
    
    except Exception as e:
        print '1', e.__doc__
        print '2', sys.exc_info()
        print '3', sys.exc_info()[0]
        print '4', sys.exc_info()[1]
        print '5', sys.exc_info()[2], 'Sorry I mean line...',traceback.tb_lineno(sys.exc_info()[2])
        ex_type, ex, tb = sys.exc_info()
        print '6', traceback.print_tb(tb)
    

    产量

    >  1  Second argument to a division or modulo operation was zero. 
    >  2  (<type 'exceptions.ZeroDivisionError'>, ZeroDivisionError('integer division
    >      or modulo by zero',), <traceback object at 0x022DCF30>) 
    >  3  <type 'exceptions.ZeroDivisionError'> 
    >  4  integer division or modulo by zero 
    >  5  <traceback object at 0x022DCF30> Sorry I mean line... 5
    >  6  File "Z:\Programming\Python 2.7\Error.py", line 5, in <module>
    >     print 1/0 
          None
    >>>
    

    【讨论】:

      【解决方案6】:

      您应该更紧密地包装您关心的语句。从回溯中提取行号将涉及且脆弱。

      【讨论】:

      • 这个问题很有趣。即使对于前来说,调试器可能比打印回溯更好用。总而言之,对我来说,你决定不回答。当我谈到这个问题时,我首先在寻找标题的答案,然后可能是关于如何正确编码/调试的建议。
      【解决方案7】:

      如果你像这样重组代码,你应该在再次引发异常时得到一个行号:

      except:
          statement7
          raise
      

      【讨论】:

      • 我应该在statement7之后写“raise”吗?为什么?
      • 如果您将其作为临时调试更改,您应该会在发生异常时看到带有行号的详细堆栈跟踪。
      【解决方案8】:

      使用通用的 except 语句通常是一种不好的编程习惯,因此您应该在 except 语句中指定要捕获的异常。 (像除了ValueError:)

      此外,您应该使用 try except 来构造应该引发异常的代码。

      【讨论】:

        【解决方案9】:

        编辑你的源代码,这样你一次删除一行,直到错误消失,这应该指出你更接近问题。

        【讨论】:

          【解决方案10】:

          我们可以通过拆分traceback.format_exc()的字符串状态得到行号。 请尝试运行以下代码..

          import traceback
          
          try:
              a = "str"
              b = 10
          
              c = a + b
          except Exception as e:
              err_lineno = str(traceback.format_exc()).split(",")[1]
              print(err_lineno)
          

          这将产生以下输出

          line 7
          

          【讨论】:

            猜你喜欢
            • 2023-04-08
            • 1970-01-01
            • 2014-06-29
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2018-11-14
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多