6 ms·
Debuggers are cool and often necessary, but I disagree with this often-expressed sentiment that print-debugging is a primitive hack for people who don't know an
by haberman 13y ago
Debuggers are cool and often necessary, but I disagree with this often-expressed sentiment that print-debugging is a primitive hack for people who don't know any better.
Debugging is determining the point at which the program's expected behavior diverges from its actual behavior. You often don't know where where/when this is happening. Print-debugging can give you a transcript of the program's execution, which you can look at to hone in on the moment where things go wrong. Stepping through a program's execution line-by-line and checking your assumptions can be a lot slower in some cases. And most debuggers can't go backwards, so if you miss the critical moment you have to start all over again.
These are two tools in the toolbox; using print debugging does not mean you are not "a boss."
- Symmetry 13y agoI tend to find myself relying on debuggers for tracking down bugs in other people's code where I might not have a good grasp of the big picture, but relying more on print statements for debugging my own code.
- mercurial 13y agoAbsolutely. Alternatively, debuggers are a godsend when there is a long deployment cycle.
- epenn 13y agoTo expand on your point, I look at print statements in the same light as goto statements. There is a time and place for both, just make sure it's the best tool to accomplish your goal. In C I often use gotos for error handling, but I wouldn't use them in situations where higher-level branching constructs are more suitable. Similarly, sometimes you don't need the features of a heavy-weight debugger but just want to check some output. Print statements are great for this.
- epenn 13y agoNormally I wouldn't comment on someone downvoting me. However I'm going to presume there is a very high probability that it's due to my analogy with the goto statement, something which most programmers seem to view as inherently evil thanks either to received dogma or to a misunderstanding of the context of Dijkstra's original paper on the subject. The point of my post was that there is a time and place for everything -- print statements in the context of this thread -- and I used gotos as an additional analogy/example. So in case anyone sees this and wonders why I would actually consciously choose to use a goto statement, please see the following goto entry in CERT's Secure Coding Standard [1] for a concise but thorough explanation. https://www.securecoding.cert.org/confluence/display/seccode/MEM12-C.+Consider+using+a+goto+chain+when+leaving+a+function+on+error+when+using+and+releasing+resources https://www.securecoding.cert.org/confluence/display/seccode...
- haberman 13y agoAgree completely. I use gotos for error handling in C, as does the Linux kernel, and I agree that fundamentalist anti-goto sentiment is unjustifiably dogmatic.
- memracom 13y agoExceptions are gotos. Just like singleton objects are global variables. And knee jerk reactions can get you killed.
- evanspa 13y agoI agree. That, coupled with keeping your functions small (doing 1 thing) and tight, and being disciplined at writing unit tests can go a LONG way when it comes to debugging with simple print statements. Normally I'm able to hone in bugs with a few strategically placed prints, and a re-run of the unit tests. Pouring over stdout log is usually trivial with an incremental search, and the print statement prefixed with some known unique chars.
- existencebox 13y agoBy "unique chars" I assume you mean things like "FML" "WHYISNTTHISWORKING" "SHOULDNTBESEEINGTHIS" and the ever useful "--------------------------------------------->"
- ufo 13y agoOne neat trick that I really like for ptrintf debugging is using conditional breakpoints and putting the call to the printing function inside the breakpoint condition. This lets you add print statements without editing the original code and makes it very easy to toggle them on and off.
- haberman 13y agoClever -- I've never heard or thought of that! When I read about this more, it sounds like you can make watchpoints conditional too. You could use this pattern to print a transcript of every change that happens to a data value! Though I'm not sure if the watchpoint condition has easy access to the source file/line, so it might not be easy to log what code was changing the value.
- masklinn 13y agoSome IDEs have support for doing that without the hack. Xcode for instance, when you set a breakpoint you can edit it to not break, and execute custom actions (logging stuff, executing debugger commands, executing a shell script, executing actionscript, playing a sound). A condition, if set, will then apply to whether the action should or should not be applied. The great part is they can all be combined, so you can setup a breakpoint which will pre-log the info you know you'll need then drop you in the visual debugger with all base information waiting for you.
- dlau1 13y agoSurprised no mention of JetBrains PyCharm. It's incredibly easy to use for debugging, even supports debugging gevent based code. I agree though, outputting print statements at different levels of severity, i.e. warning, error, info, etc. is a great way to see if things are working on a high level. For more granularity, debuggers are invaluable to figure out why a specific portion of code isn't working as expected.
- mdaniel 13y agoAnd now that they have released a community edition -- open source (Apache Licensed) -- copy of PyCharm, I cannot imagine any sane person continuing to use a "dumb" editor. All of the JetBrains products are super smart and efficient, and the community editions are no exception.
- hcarvalhoalves 13y agoI only use "print debugging" (using the logging facilities more often than not) if it's something I can leave in the codebase, like logging a function call and it's parameters, or when a routine is being skipped; then a debugger if I want to check the interface or docstring of some object or retry a call with different parameters on the REPL.
- masklinn 13y agoAlternatively, if your language/runtime/whatever supports it you can use dtrace for printf-debugging without editing the source.
- vram22 13y ago>Debuggers are cool and often necessary, but I disagree with this often-expressed sentiment that print-debugging is a primitive hack for people who don't know any better. Yes. >Stepping through a program's execution line-by-line and checking your assumptions can be a lot slower in some cases. Yes again, particularly when the code is in a loop. Whereas, if you use print-debugging, even though the output will be repeated as many times as the loop runs, you at least have the possibility of grepping to filter it down to relevant (e.g. erroneous/unexpected) output. Here's a simple Python debugging function that may be useful: http://jugad2.blogspot.in/2013/10/a-simple-python-debugging-function.html http://jugad2.blogspot.in/2013/10/a-simple-python-debugging-...
- walshemj 13y agoUm most debuggers allow you set variables and execute a loop n times
- vram22 13y agoAnd what if your bug is after the nth iteration of the loop, where the exact value of n is unknown (it's a bug, after all)? How many times are you going to set the variable and run the loop n times? Whereas with print-debugging and a grep you can filter for only unexpected/unusual output, and so narrow down to the likely cause, faster. Generalizing, of course. There are definitely cases where a debugger can be more effective, as others in this thread have said. It depends on the case.
- ori_b 13y agoI'd set a conditional breakpoint: (gdb)> break <some-location> Breakpoint 1 at .... (gdb)> cond 1 x < 42 (gdb)> cont And now, it will execute until 'x < 42' is true. If the bug is that you always expect 'x > 42', then it triggers. Although, to be honest, I mostly use a debugger as an exploratory printf these days: (gdb)> call pretty_print(my_data) I do mainly use printf as the front line of debugging, though, with several debug switches on the command line. I follow up by jumping to a debugger once I have an idea of where things are going wrong, and I can poke around at the state. I also need to look into backwards stepping. GDB can trace executions of the program, and when you see the issue pop up, you can step backwards in time to see what caused it.
- scott_s 13y agoI wrote an essay about this very thing: http://www.scott-a-s.com/traces-vs-snapshots/ http://www.scott-a-s.com/traces-vs-snapshots/
- ChikkaChiChi 13y agoPrint statements allow me to not only create my own breakpoints, but to add additional conditions, timers, resource monitors, etc. to see how my program is actually performing.
- henrik_w 13y agoI find logging/tracing (that can be enabled/disabled at run time) to be very valuable for debugging, both during development and in production. I blogged about it here: http://henrikwarne.com/2013/05/05/great-programmers-write-debuggable-code/ http://henrikwarne.com/2013/05/05/great-programmers-write-de...
- coolsunglasses 13y agoThere are better ways to do this style of debugging: https://github.com/clojure/tools.trace https://github.com/clojure/tools.trace https://github.com/coventry/Troncle https://github.com/coventry/Troncle (I can use this from nRepl'ing into production servers)
- keypusher 13y agoDoes anything like that exist for python?
- coolsunglasses 13y agoDecorators would be your best bet, but it won't be quite as nice.