December 9, 2012 will

Where are those Print statements?

When I'm debugging Python I tend to sprinkle my code liberally with print statements. Trouble is, I forget which files I added those print statements to and have to waste a few minutes tracking them down. Time which could be better spent doing pretty much anything else.

Not sure why I didn't think of this before, but I hacked together something that automatically prints the file and line of the print statement next to the output.

Here's the code:

import inspect
import sys
import os


class DebugPrint(object):
    def __init__(self, f):
        self.f = f

    def write(self, text):
        frame = inspect.currentframe()
        filename = frame.f_back.f_code.co_filename.rsplit(os.sep, 1)[-1]
        lineno = frame.f_back.f_lineno
        prefix = "[%s:%s] " % (filename, lineno)
        if text == os.linesep:
            self.f.write(text)
        else:
            self.f.write(prefix + text)

if not isinstance(sys.stdout, DebugPrint):
    sys.stdout = DebugPrint(sys.stdout)

To use it, save it as ‘debugprint.py’ then imported it somewhere. That's all you need to do. Works on Python 2.7 and probably other 2.X Pythons.

Here's what happens if you do it from the console:

>>> import debugprint
>>> print "Hello"
[<stdin>:1] Hello

For print statements in your app, you will get something like:

[foo.py:22] Hello
Use Markdown for formatting
*Italic* **Bold** `inline code` Links to [Google](http://www.google.com) > This is a quote > ```python import this ```
your comment will be previewed here
gravatar
holger
Nice one. I'd prefer a non-intrusive method, however. How about a command line tool that visits a directory's “.py” files, constructs the AST and lists all “print” statements (or print function calls in python3)? Admitted, it's a bit of work but it'd be useful without modifying any project's source code or importing special code.
gravatar
Tom
Aren't you using a revision-control tool, like git? If so, then that's the easiest way to identify and remove those debug statements. I always use ‘git diff’ before checking in changes to make sure I'm checking in just what I think I am.
gravatar
j
I always prefer to use logging http://docs.python.org/3.3/library/logging.html.

 import logging
#set up logging:
logging.basicConfig(format='%(asctime)s %(message)s')
logger = logging.getLogger(__name__)
# show warnings (remove for production)
logger.setLevel("DEBUG")
info = logger.info
warning = logger.warning
debug = logger.debug

then, instead of
 print
I use
 debug('Hello')
and get
2012-12-09 22:13:32,055 hello

You can use
 %(module)s %(lineno)d
to make it print your current module name and line number.

It is amazingly simple, more versatile, and to stop all those print commands you simple change the logger level..
gravatar
Dan
j's got the right idea. Plus, instead of removing your debug statements when you're finished, you can just turn them off by setting the log level above debug.
gravatar
Will McGugan
I prefer the humble print statement for debugging. This isn't the kind of debug output I would leave in my app so there isn't much of an advantage in using the logging module.
gravatar
dAnjou
@holger and OP

Do you know ack? No need to re-invent the wheel.
gravatar
Hans Meine

Do you know grin? Since we're talking about Python here…

gravatar
Jan Gee
A self-proclaimed Python *expert* who uses print to debug… wow. Just wow.
gravatar
j
@Will McGugan
I don't get it.
The overhead of logging is even shorter then your thing.
It is a standard, it is much more pythonic,
scales easily, and if leaving the debug commands in your code
offends your users for some reason (although after changing the loglevel they have no discernible effect),
they can be deleted in the same manner as your print statements.
Actually deleting is even easier because you cannot mistake a proper print with a debug print.

I would of course leave the debug statements in the code for the next bug-finding quest. If it is recommended for core python development, it is good enough for me.
gravatar
Will McGugan
@j I used this for debug output that is purely for tracking down a particular bug. It's either dumping a variable or just some marker so I can see if execution hit a particular point. Once the bug is fixed, the output becomes irrelevant. It wouldn't be of use to myself or anyone else in the future. Which is why I don't consider it worthy of logging.

Hiding it with a debug level is not particularly useful, since if it came back it would just be logging spam. And if it remained in the code it could still have a negative impact. For instance if I print out a database query so I can inspect the results – with something like logging.debug(repr(profile)) – it still hits the database and does a lot of string processing regardless if the logging level means the text will not make it to the logs.

So this kind of debug output should definitely be deleted. Either I use debug(“foo”) or print(“foo”). The difference is large irrelevant – especially if the logging is configured for file and line like you said. But at least with ‘print’ I know it is going to the console, no matter how logging is currently configured.
gravatar
nagisa
there's grep -R which search all files in all current working directory. I'd use it like this: `grep -R print`.
gravatar
James
I just add a comment on every print:
 print ("A string") // JAMES
Then grep when I'm done. And if I forget the next person to work with the code knows that I'm the idiot at fault.
gravatar
Wouter
J +1

You've just invented something that does the same as logging, only worse. What on earth is the overhead in

import logging; log=logging.getLogger(__name__)

on top of every module. You want that anyway because you also log stuff, don't you? Then, you can simply use log.debug(XXX) where you want to print a trace. Your version control should tell you who entered that statement and when, and if you do a diff before every commit (which I think any sensible developer should do!) you can easily see if you forgot to remove any debug messages that should not be there anymore.
gravatar
Sam
Print has its place in debugging.

We use the logging module extensively and log thousands of messages a day. Each message is carefully assigned a level and we have gui and command line tools to make sure we can see the messages we need.

But for something temporary where your tracking down a bug there's nothing wrong with print. There are some messages that I just don't want written to files, etc. That's where print can come in. This is a clever hack!
gravatar
Scott
Why the hostility in the comments? I love this.
gravatar
Will McGugan
Not sure! I had no idea it would be so contentious…
gravatar
Gary Robinson
“A self-proclaimed Python *expert* who uses print to debug… wow. Just wow.”

How can people be so stupidly arrogant? There are pluses and minuses and intelligent, well-informed people can choose one or the other.

BTW, I saw an interview with Guido in which he mentioned that when debugging, he likes to use a lot of print statements. Or maybe he doesn't qualify as a “Python ‘expert’”?
gravatar
Hans Meine

You can remove this condition:

if not isinstance(sys.stdout, DebugPrint):

Since DebugPrint has just been defined above, the condition will always be True. (One could check whether 'DebugPrint' in str(type(sys.stdout)), or even whether not isinstance(sys.stdout, file), but one may also rely on the code being only executed for the first import.

Also, the rsplit() part can be simplified using os.path.basename.