简体   繁体   English

定位python代码中发生异常的行号

[英]Locating the line number where an exception occurs in python code

I have a code similar to this:我有一个类似的代码:

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

except:
      statement7

Here, I am sure that the exception occurs in If x: block, but I would like to know in which statement of If x: block the exception occurs.在这里,我相信所发生的例外If x:块,但我想知道其中的发言If x:阻止出现异常。 Is there a way to get the line number where the exception occurs?有没有办法获取发生异常的行号?

Regards,问候,

what about this:那这个呢:

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

this is the straightforward workaround but I suggest to use a debugger这是直接的解决方法,但我建议使用调试器

or even better, use the sys module :D甚至更好,使用 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

I believe the several answers here recommending you manage your try/except blocks more tightly are the answer you're looking for.我相信这里建议您更严格地管理try/except块的几个答案是您正在寻找的答案。 That's a style thing, not a library thing.那是一种风格,而不是图书馆的东西。

However, at times we find ourselves in a situation where it's not a style thing, and you really do need the line number to do some other programattic action.然而,有时我们发现自己在一个情况下它不是一种风格的东西,你真的需要行号做一些其他programattic行动。 If that's what you're asking, you should consider the traceback module.如果这就是您要问的,您应该考虑traceback模块。 You can extract all the information you need about the most recent exception.您可以提取有关最近异常的所有信息。 The tb_lineno function will return the line number causing the exception. 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

Newer versions of the traceback plumbing fix the issue prior to 2.3, allowing the code below to work as it was intended: (this is the "right way")较新版本的回溯管道修复了 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)

You should run your program in a debugger, such as pdb .您应该在调试器中运行您的程序,例如pdb This will allow you to run your code normally, and then examine the environment when something unexpected like this occurs.这将允许您正常运行代码,然后在发生此类意外情况时检查环境。

Given a script named 'main.py', run it like this:给定一个名为“main.py”的脚本,像这样运行它:

python -m pdb main.py

Then, when your program starts, it will start in the debugger.然后,当您的程序启动时,它将在调试器中启动。 Type c to continue until the next breakpoint (or crash).键入c继续直到下一个断点(或崩溃)。 Then, you can examine the environment by doing things like print spam.eggs .然后,您可以通过执行诸如print spam.eggs类的操作来检查环境。 You can also set breakpoints by doing pdb.set_trace() (I commonly do import pdb; pdb.set_trace() ).您还可以通过执行pdb.set_trace() (我通常执行import pdb; pdb.set_trace() )来设置断点。

Additionally, what do you mean that it is "okay" for 'statement 3' to raise the exception?此外,“语句 3”引发异常是什么意思? Are you expecting the exception?你期待例外吗? If so, it might be better to write a try/except block around this statement, so that the program can continue.如果是这样,最好在此语句周围编写一个 try/except 块,以便程序可以继续。

I've done the following before:我以前做过以下工作:

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

 except:
    print "exception occurred doing ", doing

The advantage over printing checkpoints is there's no log output unless there actually is an exception.打印检查点的优点是没有日志输出,除非确实有异常。

Building on JJ above..建立在JJ上面..

The advantage of using system errors over statements is they record more specific information which will aid debugging later (believe me I get a lot)使用系统错误而不是语句的优点是它们记录了更具体的信息,这将有助于以后调试(相信我我得到了很多)

eg.例如。 I record them to a text file, so after my programs have automatically run overnight on the server, I can retrieve any issues, and have enough information to quicken the repair!我将它们记录到一个文本文件中,所以在我的程序在服务器上自动运行一夜之后,我可以检索任何问题,并有足够的信息来加快修复!

More Info... Traceback & Sys更多信息... 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)

Yields产量

>  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
>>>

You should wrap the statements you care about more tightly.您应该更紧密地包装您关心的语句。 Extracting the line number from the traceback is going to be involved and fragile.从回溯中提取行号将涉及且脆弱。

If you restructure the code like so, you should get a line number when the exception is raised again:如果你像这样重构代码,当再次引发异常时你应该得到一个行号:

except:
    statement7
    raise

Using a general except statement is usually a bad programming practice, so you should specify in your except statement what exception you want to catch.使用通用的 except 语句通常是一种糟糕的编程习惯,因此您应该在您的 except 语句中指定要捕获的异常。 ( like except ValueError: ) (比如除了 ValueError: )

Moreover, you should surround with a try except structure the bits of code that are supposed to be raising an exception.此外,您应该用 try except 结构化应该引发异常的代码位。

we can get the line number by splitting the string state of the traceback.format_exc() .我们可以通过拆分traceback.format_exc()的字符串状态来获取行号。 please try running the following code..请尝试运行以下代码..

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)

this will produce the following output这将产生以下输出

line 7

编辑您的源代码,以便一次删除一行,直到错误消失,这将使您更接近问题。

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

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