PyWart: The problem with "print"

Chris Angelico rosuav at gmail.com
Sun Jun 2 22:02:44 EDT 2013


On Mon, Jun 3, 2013 at 10:16 AM, Jason Swails <jason.swails at gmail.com> wrote:
> Copy-and-pasting your timeit experiment on my machine yields different
> timings (Python 2.7):
>
>>>> import sys
>>>> timeit.timeit('debugprint("asdf")','def debugprint(*args):\n\tif not
>>>> DEBUG: return\n\tsys.stdout.write(*args)\nDEBUG=False',number=1000000)
> 0.15644001960754395
>
> which is ~150 ns/function call, versus ~1300 ns/function call.  And there
> may be even more extreme examples, this is just one I was able to cook up
> quickly.

The exact time will of course vary enormously. My point still would
stand at 1300ns; it's still extremely low compared to many other
overheads.

> This is, I'm sad to say, where my alignment with RR ends.  While I use
> prints in debugging all the time, it can also become a 'crutch', just like
> reliance on valgrind or gdb.  If you don't believe me, you've never hit a
> bug that 'magically' disappears when you add a debugging print statement
> ;-).

Yes, I've had situations like that. They are, however, EXTREMELY rare
compared to the times when a bug magically becomes shallow when you
add a debugging print!

> The easiest way to eliminate these 'dead' calls is to simply comment-out the
> print call, but I would be quite upset if the interpreter tried to outsmart
> me and do it automagically as RR seems to be suggesting.  And if you're
> actually debugging, then you typically only add a few targeted print
> statements -- not too hard to comment-out.  If it is, and you're really that
> lazy, then by all means add a new, greppable function call and use a sed
> command to comment those lines out for you.

Yes. I also have high hopes for some of the cool AST manipulation
that's being developed at the moment; it should be relatively easy to
have a simple flag that controls whether debugprint (btw, I'd shorten
the name) represents code or no-code.

But consider all the other things that you probably do in your Python
programs. Every time you reference something as "module.name", you
require a lookup into the current module's  namespace to find the
module name, then into that module's namespace to find the object you
want. Snagging names as locals is a common optimization, but is far
from universally applied. Why? Because the readability cost just isn't
worth it. We use Python because it is "fast enough", not because it
lets us squeeze every CPU cycle out of the code.

That said, I can often smoke Python with Pike, thanks to a few rather
cool optimizations (including looking up module names at compile time,
which reduces what I just said above). Maybe in the future some of
these optimizations will be done, I don't know. But for 99.9% of
Python scripts, you will *never* see the performance difference.

ChrisA



More information about the Python-list mailing list