By Vasudev Ram
[ Update: I do know about Python's logging module but felt it was overkill for my current needs, and also wanted more flexibility. ]
[ Update 2: Made some minor improvement to the code for better output. You can now print a debug message without any associated values. ]
I just whipped up this simple debugging function to help me debug my Python programs:
# vr_debug.py # Debug utility functions by VR. # Author: Vasudev Ram - http://www.dancingbison.com # Description: Simple utility functions for debugging Python programs. import sys import os def vr_debug(message, *values): vr_debugging = os.getenv("VR_DEBUG") if vr_debugging is None: # Debugging is off, do nothing. return if len(values) == 0: print message, else: print message, ":", #print "len(values):", len(values) for value in values: #print repr(value), " ", print repr(value), print def main(): # Test the vr_debug function with some calls. vr_debug('z') # Debug message without any associated values. # Debug messages with values: vr_debug('a', 1) vr_debug('b', 1, "hi") vr_debug('c', 1, "hi", True) vr_debug('d', 1, "hi", True, [2, 3]) vr_debug('d', 1, "hi", True, [2, 3], {'a': 'apple', 'b': 'banana'}) if __name__ == '__main__': main() # EOF
To use the vr_debug function (as shown in the above program), you have to set an environment variable VR_DEBUG to some non-null value, say 1:
C:\>set VR_DEBUG=1Then you can run the program to test the debug function, with:
C:\>python vr_debug.pyHere is its output:
z a : 1 b : 1 'hi' c : 1 'hi' True d : 1 'hi' True [2, 3] d : 1 'hi' True [2, 3] {'a': 'apple', 'b': 'banana'}To turn off debugging, just set VR_DEBUG to a null value:
C:\>set VR_DEBUG=
Note: The above environment variable settings were for Windows. For Linux/UNIX, using bash, you would do this:
$ export VR_DEBUG=1to set the environment variable, but the unset command to unset it:
$ unset VR_DEBUG
The above program included both the vr_debug function and a few tests of it. To use the vr_debug function in your own code, just copy the file vr_debug.py to somewhere on your PYTHONPATH and then import it into any Python files in which you want to use it:
from vr_debug import vr_debugNow you can call it just as in the above program.
This is just a simple debug function, improvements are possible, such as passing an output destination argument, with a default of sys.stderr (so that output is un-buffered, unlike with the print command), and also so that a different destination can be given, such as a file opened for writing. To do that, you would have to change all the print statements to something like:
out_fil.write(...), and add
out_fil=sys.stderras another argument to the vr_debug function.
I've written a few different variations of such debugging functions over the years, in Python as well as other languages, but have somehow never seemed to arrive at a solution that satisfies me.
On the other hand, there is something to be said for KISS ...
For another Python debugging technique, see my earlier post:
Using sys._current_frames() and the Python traceback module for debugging
- Vasudev Ram - Dancing Bison Enterprises
Contact me
7 comments:
Do you really want to check the VR_DEBUG environment variable every time vr_debug() is called? For that matter, do you really want to incur a check on every call even if debugging is turned off? How about something like this:
if os.getenv("VR_DEBUG"):
def vr_debug(message, *values):
if len(values) == 0:
print message,
else:
print message, ":",
#print "len(values):", len(values)
for value in values:
#print repr(value), " ",
print repr(value),
print
else:
def vr_debug(message, *values):
pass
(Sorry about the formatting, I couldn't figure out an HTML tag that would be accepted.)
Thanks for your version.
Yes, I did realize that the environment variable gets checked in each call to the vr_debug function, but the overhead of the os.getenv() call is quite low, because there is no disk access; it just gets the value from memory:
http://docs.python.org/2/library/os.html#os.environ
But your version avoids even that low overhead. I hadn't thought of defining alternative versions of the function within the if and else clauses, though I knew that was possible in Python, in general. A useful technique ...
As for the formatting, yes, the indentation is gone when I published your comment, but no problem. FYI, I used the pre HTML tag in the original post, which works there. Let me check if it works in the comments by posting your code as a new comment below, using the pre tag.
Nope, pre tag didn't work - Blogger gave a message that it is not allowed.
Anyway, another minor improvement to the code, though I'm not posting it again - I moved the for loop to be under the else clause, since there is no sense running it if len(values) is 0.
You should check out the python logging module. It does all this and more and is part of the standard library.
I do know about Python's logging module, and have also used Java's logging modules, such as log4j and another, and have extended them in the past.
See my update near the top of my post, that starts with "I do know about Python's logging module".
Like I said there, I wanted flexibility. One thing I didn't mention in the post, is that I plan to add more features to the debugging function over time. I could do that with Python's logging module, of course, but chose to roll my own for my current requirement.
Have you seen q - Quick-and-dirty debugging output for tired programmers (https://pypi.python.org/pypi/q/)?
No, hadn't seen it earlier. Thanks, will have a look.
Post a Comment