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
16 Responses to "Where are those Print statements?"
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.
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.
I always prefer to use logging http://docs.python.org/3.3/library/logging.html.
then, instead of
printI use
and get
You can use
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..
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.
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.
@holger and OP
Do you know ack? No need to re-invent the wheel.
A self-proclaimed Python *expert* who uses print to debug… wow. Just wow.
@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.
@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.
there's grep -R which search all files in all current working directory. I'd use it like this: `grep -R print`.
I just add a comment on every print:
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.
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.
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!
Why the hostility in the comments? I love this.
Not sure! I had no idea it would be so contentious…
“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’”?