10

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. Is there a way to get the line number where the exception occurs?

Regards,

4
  • 2
    You don't mention why you want this. For debugging a problem? So that statement7 can do something different depending on where the exception was raised? Can you tell us more? Commented Aug 5, 2011 at 19:47
  • In my code the exception should not occur in statement 1 or statement 2. if it does, then either of statement1 or 2 is faulty. it is acceptable to have it in statement3. That's why I would like to know in which line there is exception. Commented Aug 5, 2011 at 19:50
  • But what will you do with the information? Do you need it once to fix the program, or do you need it at runtime? Commented Aug 5, 2011 at 20:24
  • I need it once to fix the faulty lines. Now I have found the faulty line, thanks all! Commented Aug 5, 2011 at 21:08

10 Answers 10

21

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

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 
Sign up to request clarification or add additional context in comments.

1 Comment

Updating: exc_traceback has been replaced by last_traceback (e.g. docs.python.org/2/library/traceback.html)
13

I believe the several answers here recommending you manage your try/except blocks more tightly are the answer you're looking for. 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. If that's what you're asking, you should consider the traceback module. 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.

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

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) 

2 Comments

thanks, I tried as you said but I got the following: exception occured in line number: <function tb_lineno at 0x2aaaace83140>
tb_lineno is a function, not an attribute. It takes the traceback as a parameter. I edited the post to be more clear. try "print traceback.tb_lineno(sys.exc_info()[2])" -- make sure to add the paren's.
4

You should run your program in a debugger, such as 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:

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). Then, you can examine the environment by doing things like print spam.eggs. You can also set breakpoints by doing pdb.set_trace() (I commonly do import pdb; pdb.set_trace()).

Additionally, what do you mean that it is "okay" for 'statement 3' to raise the exception? 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.

1 Comment

Epic! Worked super awesome with Django, ex. python -m pdb manage.py syncdb --settings=settings_development or python -m pdb manage.py runserver --settings=settings_development.
3

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.

Comments

3

Building on JJ above..

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

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

Comments

2

You should wrap the statements you care about more tightly. Extracting the line number from the traceback is going to be involved and fragile.

1 Comment

The question is interesting as is. Even if for ex a debugger could be of better use than printing a traceback. All in all, for me, you are deciding just not to answer. When I come to that question, I am looking for an answer to the title above all, then maybe suggestions about how to code/debug correctly.
2

If you restructure the code like so, you should get a line number when the exception is raised again:

except: statement7 raise 

2 Comments

I should write "raise" after statement7? Why?
IF you do it as a temporary debugging change, you should see a detailed stack trace with line numbers when your exception occurs.
1

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. ( like except ValueError: )

Moreover, you should surround with a try except structure the bits of code that are supposed to be raising an exception.

Comments

0

Edit your source code, so that you remove one line at a time, until the error disappears, and that should point you closer to the problem.

Comments

0

we can get the line number by splitting the string state of the 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 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.