I have been coding a lot in Python of late. And I have been working with data that I haven't worked with before, using formulae never seen before and dealing with huge files. All this made me write a lot of print statements to verify if it's all going right and identify the points of failure. But, generally, outputting so much information is not a good practice. How do I use the print statements only when I want to debug and let them be skipped when I don't want them to be printed?
6 Answers
The logging
module has everything you could want. It may seem excessive at first, but only use the parts you need. I'd recommend using logging.basicConfig
to toggle the logging level to stderr
and the simple log methods, debug
, info
, warning
, error
and critical
.
import logging, sys
logging.basicConfig(stream=sys.stderr, level=logging.DEBUG)
logging.debug('A debug message!')
logging.info('We processed %d records', len(processed_records))

- 112,946
- 110
- 377
- 526
-
13Also, in case you had trouble installing this module like me; logging is part of the standard library - no need for pip install even when using a virtual environment – Amr Jul 17 '18 at 11:40
-
How does one set the level of the logging such that it only prints errors and not debug messages? – Eduardo Pignatelli Jun 10 '20 at 12:19
-
@EduardoPignatelli set `level`, in the `basicConfig` call, to `logging.ERROR`. – Matt Joiner Jun 15 '20 at 00:49
-
1I am afraid this does not work on jupyter lab 1.2.6. You can set the logging level once, and re-setting is using `logging.basicConfig(stream=sys.stderr, level=logging.ERROR)` will have no effect. Restarting the kernel and setting the new level works, but that's a workaround for me. – Eduardo Pignatelli Jun 15 '20 at 14:21
-
@EduardoPignatelli you should ask another question for this. But likely you'll need to directly change the level on the root logger, jupyter is probably calling basicConfig before you. – Matt Joiner Jun 15 '20 at 22:41
A simple way to do this is to call a logging function:
DEBUG = True
def log(s):
if DEBUG:
print s
log("hello world")
Then you can change the value of DEBUG
and run your code with or without logging.
The standard logging
module has a more elaborate mechanism for this.

- 951,095
- 183
- 1,149
- 1,285
-
8It's probably better in the long run to use the supplied [logging](http://docs.python.org/library/logging.html) module than roll your own (even though it looks more complicated). – mgiuca Jul 05 '11 at 08:00
-
15True, but it's worthwhile understanding how one *could* roll their own. – Greg Hewgill Jul 05 '11 at 08:03
-
1Indeed. The above is a good idea of how `logging` works (at a very simple level). – mgiuca Jul 05 '11 at 08:05
-
-
1I would replace `s` with `*s` so you can pass comma delimited values like in `print()` function. – Warf Jun 16 '22 at 11:51
Use the logging built-in library module instead of printing.
You create a Logger
object (say logger
), and then after that, whenever you insert a debug print, you just put:
logger.debug("Some string")
You can use logger.setLevel
at the start of the program to set the output level. If you set it to DEBUG, it will print all the debugs. Set it to INFO or higher and immediately all of the debugs will disappear.
You can also use it to log more serious things, at different levels (INFO, WARNING and ERROR).

- 20,958
- 7
- 54
- 70
First off, I will second the nomination of python's logging framework. Be a little careful about how you use it, however. Specifically: let the logging framework expand your variables, don't do it yourself. For instance, instead of:
logging.debug("datastructure: %r" % complex_dict_structure)
make sure you do:
logging.debug("datastructure: %r", complex_dict_structure)
because while they look similar, the first version incurs the repr() cost even if it's disabled. The second version avoid this. Similarly, if you roll your own, I'd suggest something like:
def debug_stdout(sfunc):
print(sfunc())
debug = debug_stdout
called via:
debug(lambda: "datastructure: %r" % complex_dict_structure)
which will, again, avoid the overhead if you disable it by doing:
def debug_noop(*args, **kwargs):
pass
debug = debug_noop
The overhead of computing those strings probably doesn't matter unless they're either 1) expensive to compute or 2) the debug statement is in the middle of, say, an n^3 loop or something. Not that I would know anything about that.

- 41,842
- 6
- 48
- 60
-
There's more information on this important topic under 'optimisation' in the logging howto: https://docs.python.org/3/howto/logging.html#optimization – Martin CR May 09 '20 at 08:25
-
`Because while they look similar, the first version incurs the repr() cost even if it's disabled. The second version avoid this.` - As dummy I ask myself, where is this documented? What is a *repr() cost*? – ViRuSTriNiTy Apr 12 '23 at 15:05
-
It's not documented, it's implicit: doing `foo("%r" % bar)` "obviously" executes the interpolation (% operator) before passing the result to `foo`. Hence, even if `foo()` does nothing with the result, the computational cost of doing the interpolation is still incurred. – pjz Apr 20 '23 at 16:15
I don't know about others, but I was used to define a "global constant" (DEBUG
) and then a global function (debug(msg)
) that would print msg
only if DEBUG == True
.
Then I write my debug statements like:
debug('My value: %d' % value)
...then I pick up unit testing and never did this again! :)

- 42,153
- 26
- 121
- 131
-
Unit testing ha. Okay, thats another thing to be picked up then :( – crazyaboutliv Jul 05 '11 at 08:01
-
2I don't want to discourage unit testing -- it is essential. But I don't think it's a substitute for logging, even as a debugging technique. I still do a lot of printing to quickly test things. – mgiuca Jul 05 '11 at 08:02
-
@crazyaboutliv - Unit testing done properly is great. Have a look to [this chapter](http://diveintopython.org/unit_testing/index.html) of diving into python for a snappy, concise, easy-to-follow presentation – mac Jul 05 '11 at 08:03
-
@mgiuca - I do quick printing too, but it's just a couple or so of `print()` while bringing up my code to the required level to pass the test. I never end up with huge amount of `print()` all over the place. Logging is cool too! :) – mac Jul 05 '11 at 08:06
-
I am ending up with too many of them. And later, I am importing methods from that program to another one and it ends up printing a lot of junk that is not required. So, thats why i need to use something :) – crazyaboutliv Jul 05 '11 at 08:08
-
2@mac It looks like your link now requires an explicit 'www' - it is now [hosted here](http://www.diveintopython.net/unit_testing/index.html). – culix Sep 13 '12 at 06:46
-
@culix - Thank you for the comment. Alas, it is not possible to edit comments after a few minutes one enters them into the system... I upvoted your comment hoping it will be more visible. BTW: the link is broken because the author of "Dive into Python", Mark Pilgrim, [committed infosuicide a while back](http://en.wikipedia.org/wiki/Mark_Pilgrim_%28software_developer%29#.22Disappearance.22_from_the_Internet). – mac Sep 13 '12 at 12:27
A better way to debug the code is, by using module clrprint
It prints a color full output only when pass parameter debug=True
from clrprint import *
clrprint('ERROR:', information,clr=['r','y'], debug=True)

- 83
- 5