Finding a print statement in Python
Question:
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)
Answers:
Use grep:
grep -rn print .
Using grep with a cleverly constructed regex (does not begin or end with quotes) seems to be your best bet.
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
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 !)
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
It can be hard to find print statements littered in code. You can use grep -r print .
, but you may find lots of false positives. An IDE can help you track it down faster.
The correct way to handle this is to use the logging
package and have your print statements like this:
logging.info("some value: %s",value)
And then you can turn it on or off with the logging system, which is well understood.
But you know, also use a global variable called debug
and set it to True
to enable printing. Like this:
(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
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.
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 %rn" % 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.
For Python3 i use it patched print for printing out filename, line No and function
import builtins
from inspect import getframeinfo, stack
original_print = print
def print_wrap(*args, **kwargs):
caller = getframeinfo(stack()[1][0])
original_print("FN:",caller.filename,"Line:", caller.lineno,"Func:", caller.function,":::", *args, **kwargs)
builtins.print = print_wrap
Based on Andrew’s answer above I am now using
import sys
class RaiseOnPrint(object):
def write(self, *args, **kwargs):
raise RuntimeError("print was called")
def flush(*args, **kwargs):
pass
sys.stdout = RaiseOnPrint()
to raise a RuntimeError
when print
is called.
Below is a sample outcome (in a jupyter notebook):
RuntimeErrorTraceback (most recent call last)
<ipython-input-6-7f55d16e81f1> in <module>()
5 a()
6
----> 7 b()
<ipython-input-6-7f55d16e81f1> in b()
3
4 def b():
----> 5 a()
6
7 b()
<ipython-input-6-7f55d16e81f1> in a()
1 def a():
----> 2 print "I am here"
3
4 def b():
5 a()
<ipython-input-5-7e896ec60c87> in write(self, *args, **kwargs)
4 class RaiseOnPrint(object):
5 def write(self, *args, **kwargs):
----> 6 raise RuntimeError("print was called")
7 def flush(*args, **kwargs):
8 pass
RuntimeError: print was called
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)
Use grep:
grep -rn print .
Using grep with a cleverly constructed regex (does not begin or end with quotes) seems to be your best bet.
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
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 !)
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
It can be hard to find print statements littered in code. You can use grep -r print .
, but you may find lots of false positives. An IDE can help you track it down faster.
The correct way to handle this is to use the logging
package and have your print statements like this:
logging.info("some value: %s",value)
And then you can turn it on or off with the logging system, which is well understood.
But you know, also use a global variable called debug
and set it to True
to enable printing. Like this:
(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
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.
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 %rn" % 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.
For Python3 i use it patched print for printing out filename, line No and function
import builtins
from inspect import getframeinfo, stack
original_print = print
def print_wrap(*args, **kwargs):
caller = getframeinfo(stack()[1][0])
original_print("FN:",caller.filename,"Line:", caller.lineno,"Func:", caller.function,":::", *args, **kwargs)
builtins.print = print_wrap
Based on Andrew’s answer above I am now using
import sys
class RaiseOnPrint(object):
def write(self, *args, **kwargs):
raise RuntimeError("print was called")
def flush(*args, **kwargs):
pass
sys.stdout = RaiseOnPrint()
to raise a RuntimeError
when print
is called.
Below is a sample outcome (in a jupyter notebook):
RuntimeErrorTraceback (most recent call last)
<ipython-input-6-7f55d16e81f1> in <module>()
5 a()
6
----> 7 b()
<ipython-input-6-7f55d16e81f1> in b()
3
4 def b():
----> 5 a()
6
7 b()
<ipython-input-6-7f55d16e81f1> in a()
1 def a():
----> 2 print "I am here"
3
4 def b():
5 a()
<ipython-input-5-7e896ec60c87> in write(self, *args, **kwargs)
4 class RaiseOnPrint(object):
5 def write(self, *args, **kwargs):
----> 6 raise RuntimeError("print was called")
7 def flush(*args, **kwargs):
8 pass
RuntimeError: print was called