tags:

views:

276

answers:

8

Sometimes I leave debugging printing statements in my project and it is difficult to find it. Is there any way to find out what line is printing something in particular?

Sidenote

It appears that searching smart can solve the majority of cases. In Pydev (and other IDEs) there is a Search function which allows searching through all files in a project. Of course, a similar effect can be obtained using grep with the -rn flag, although you only get line numbers instead of direct links.

"print(" works much better within my code and often there is extra text in a print statement that can be searched for with a regular expression. The most difficult case is when you have just written print(x), although this can be searched for a regular expression where the value inside x does not begin or end with quotes (thanks! BecomingGuro)

+4  A: 

Use grep:

grep -rn print .

Pomyk
+1  A: 

Using grep with a cleverly constructed regex (does not begin or end with quotes) seems to be your best bet.

Lakshman Prasad
I really should use regex searching more. However, as noted above, there are some cases this doesn't cover
Casebash
"does not begin or end with quotes" - that is a brilliant trick.
Casebash
what's wrong with searching for just "print"? oh wait ... is that the clever regex?
hasen j
hasen: The op originally mentioned there are so many other print statements which causes the problem. If "search for print" is an answer to the question "How do I find print", its not even a question; at least not the one that gets 8 answers.
Lakshman Prasad
+4  A: 

This article can prove very valuable in doing that. Look for the line events and extract the method name from the frame ( if I remember correctly ). More information can be found here

Geo
Wow, that is just so totally awesome. I can imagine some cool hacks such as adding a ## onto the end of every line that you want to follow. It may end up being to slow, but it would be possible to write a version that caches the calls and so each line only has to be examined once
Casebash
Neat feature here, but be careful about using it to create completely unmaintable code...
vy32
I think that it is mainly for debugging
Casebash
+2  A: 

The easiest way would be to use a "debug_print" function instead of plain "print".

That way you could just redefine the function and be sure you did not miss one... and still have them handy if you need to debug that code again instead of editing your code back and forth each time.

(Yes leaving debug_print calls can eat some performance : just remove them when it's the case)

Spotting "debug only" statements in your code is a very good reason to do a diff before comitting any code in your revision control system ! (knowing what to put in your commit comments being a second good reason to do it !)

siukurnin
The problem with this is that this takes more effort to type and would slow down debugging. Maybe I should define my statement as _p
Casebash
Wouldn't it be better to use the `logging` module instead? If I remember correctly, it can be deactivated when you don't need it ( so you don't lose performance when you don't need to ).
Geo
I agree with Geo, using the logging module would be much cleaner, that is what it has been made for.
RedGlyph
It looks pretty complex and seems like a bit of overkill for a lot of basic debug printing. However, for more complex problems, it could be incredibly helpful. I'm definitely going to have to learn how to use it as soon as I get a chance
Casebash
Sorry, this was a good solution, but someone just posted one that is even better!
Casebash
A: 

This probably doesnt answer your question directly, but you can get away with tons of print statements if you use pdb (python debugger) in a way to effectively debug and write code.

I know it works, because 99% of time you simple dont wanna print stuff, but you wanna set a breakpoint somewhere and see what the variables are and how far the program has reached.

HTH

jeffjose
I'm actually using the Pydev debugger and you can in fact view variables/expressions by just mouse over/selection which is pretty cool
Casebash
+1  A: 

I typically do this in my code:

(near the top):

debug=True

(later on)

if debug: print "This is a debug statement. x=",x

Then, when I want to take out all of the debugging statement, I change the debug to:

debug=False

vy32
Defining a function leads to less typing
Casebash
True. You can certainly put the if statement inside a function. I find the function a bit harder to read, though. And, of course, it's less efficient...
vy32
+1  A: 

Use a printf function instead. The following is from Infrequently Answered Python Questions

def printf(format, *args): 
    """Format args with the first argument as format string, and print.
    If the format is not a string, it is converted to one with str.
    You must use printf('%s', x) instead of printf(x) if x might
    contain % or backslash characters."""
    print str(format) % args,

Now, when you move from debug to production, you redefine printf like so:

def printf(format, *args):
    pass

The advantage to doing it this way, is that if you have to go back and maintain the code to add features or fix a bug, you can turn printf back on.

Michael Dillon
+6  A: 

You asked about static solutions. Here's a dynamic one. Suppose you run the code and see an errant print or write to sys.stdout, and want to know where it comes from. You can replace sys.stdout and let the exception traceback help you:

>>> import sys
>>> def go():
...   sys.stdout = None
...   print "Hello!"
... 
>>> go()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in go
AttributeError: 'NoneType' object has no attribute 'write'
>>> print "Here"
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'NoneType' object has no attribute 'write'
>>>

For something a bit more sophisticated, replace 'sys.stdout' with something which reports where the print statement is located. I'll use traceback.print_stack() to show the full stack, but you can do other things like using sys._getframe() to look up one stack level in order to get the line number and filename.

import sys
import traceback

class TracePrints(object):
  def __init__(self):    
    self.stdout = sys.stdout
  def write(self, s):
    self.stdout.write("Writing %r\n" % s)
    traceback.print_stack(file=self.stdout)

sys.stdout = TracePrints()

def a():
  print "I am here"

def b():
  a()

b()

Here's the output

Writing 'I am here'
  File "stdout.py", line 19, in <module>
    b()
  File "stdout.py", line 17, in b
    a()
  File "stdout.py", line 14, in a
    print "I am here"
  File "stdout.py", line 9, in write
    traceback.print_stack(file=self.stdout)
Writing '\n'
  File "stdout.py", line 19, in <module>
    b()
  File "stdout.py", line 17, in b
    a()
  File "stdout.py", line 14, in a
    print "I am here"
  File "stdout.py", line 9, in write
    traceback.print_stack(file=self.stdout)

If you go this route, see also the 'linecache' module, which you can use to print the contents of the line. Take a look at the implementation of traceback.print_stack for details of how to do that.

Andrew Dalke
Thanks, that is genius!
Casebash