[Python-ideas] Should __builtins__ have some kind of pass-through print function, for debugging?

Nathaniel Smith njs at pobox.com
Fri Apr 27 04:29:42 EDT 2018


Hi all,

This came up in passing in one of the PEP 572 threads, and I'm curious
if folks think it's a good idea or not. When debugging, sometimes you
have a somewhat complicated expression that's not working:

# Hmm, is func2() returning the right thing?
while (func1() + 2 * func2()) < func3():
    ...

It'd be nice to print out what func2() returns, but to do that we have
to refactor this code, which might be rather tricky in a case like
this. I think if you want to use print() directly here, the simplest
way to do that is:

while True:
    tmp = func2()
    print(tmp)
    if not (func1() + 2 * func2()) < func3()):
        break
    ...

Obviously this is annoying and error prone – especially for beginners,
who are the ones most likely to need to print out lots of stuff to
figure out why their code isn't working. (Chris Angelico mentioned
that he finds this to be a common problem when teaching beginners.)

There is a better way: if you define a trivial helper like:

# "debug print": prints and then returns its argument
def dp(obj):
    print(repr(obj))
    return obj

then the rewritten code becomes:

while (func1() + 2 * dp(func2())) < func3():
    ...

Of course, this is trivial -- for me or you. But the leap to first
realize that this is a useful thing, and then implement it correctly,
is really asking a lot of beginners, who by assumption are struggling
to do *anything* with Python syntax. And similarly, putting a package
on PyPI is useful (cf. the venerable 'q' package), but still adds a
significant barrier to entry: you need to be able to install packages,
and you need to add an import. In fact, I can imagine that you might
want to teach this trick even before you teach what imports are.

So, would it make sense to include a utility like this in __builtins__?

PEP 553, the breakpoint() builtin, provides some relevant precedent.
Looking at it, I see it also emphasized the value of letting IDEs
override the debugger, and I can see some similar value here: e.g.
fancy REPLs like Spyder or Jupyter could potentially capture the
objects passed to dp() and make them available for interactive viewing
(imagine if they're like a large dataframe or something).

Points to argue over if people like the general idea:

- The name: p(), dp(), debug(), debugprint(), ...?
- __str__ or __repr__? Presumably __repr__ since it's a debugging tool.
- Exact semantics: there should probably be some way to add a bit of
metadata that gets printed out, for cases like:

while (dp(func1(), "func1") + 2 * dp(func2(), "func2")) < dp(func3(), "func3"):
    ...

Maybe other tweaks would be useful as well.

-n

-- 
Nathaniel J. Smith -- https://vorpus.org


More information about the Python-ideas mailing list