ANNOUNCE: A Python 2.1 release candidate!

Tim Peters tim.one at home.com
Sat Apr 14 03:29:10 EDT 2001


[Don O'Donnell]
> ...
> I use the __debug__ built-in variable, not only for it's intended
> use as an implied conditional on the assert statement, but also
> explicitly as a conditional on print statements used for debugging,
> as:
>     if __debug__: print "function bleep entered with arg: %s" % arg

Stuffing code blocks under "if __debug__" is also an intended use, although
stuffing purely informative prints in those blocks probably isn't a good idea
(see below).  I'd use, e.g., a vrbl named TRACE instead for tracing function
entries and exits.

> thus all debugging is under control of a single variable.
>
> I find it very useful to be able to assign to __debug__.  There are at
> least two situations where I use it regularly:
>
> 1.  As a run-time debugging switch.  By providing an interactive user
> option switch which sets __debug__ to 0 or 1 dynamically at run time
> through user input (menu or command prompt).  This allows me to
> easily turn off debugging when it's not needed and turn it back on
> when it is.

Except that it doesn't work correctly for that:  if you (or your users) ever
run Python with -O, your "if __debug__:" blocks vanish entirely, and then you
can set __debug__ to 1 until you're blue in the face and it won't make any
difference:

>type debug.py
__debug__ = 1
__debug__ = 1
__debug__ = 1
__debug__ = 1
__debug__ = "I'm getting blue in the face!"
__debug__ = 1

if __debug__:
    print "Ha!  I win!"
else:
    print "Oops"

>python -O debug.py
Oops

That's "a feature", btw:  __debug__ was designed so that the code under its
control doesn't even get compiled under -O.  For example, from an interactive
Python -O session:

>>> def f():
...     if __debug__:
...         print "hi"
...
>>> import dis
>>> dis.dis(f)
          0 LOAD_CONST               0 (None)
          3 RETURN_VALUE
>>>

Note that there's no sign of the "if __debug__", or of the code block it
controls, if the bytecode for f.  That's why runtime setting of __debug__ has
no effect under -O.

If you want a variable that won't make code go away by magic at compile time,
define your own.  For example, Guido usually uses a vrbl named DEBUG for that
purpose.  I've often found it useful to create a debug.py module, that exists
only to export debug.level and debug.flags ints and symbolic constants:  a
true/false-only debug flag is too crude for what I usually want anyway (even
if its -O behavior didn't make trying to change it at runtime futile).

> ...
> Without the ability to rebind the __debug__ variable, the only method
> I know of to change it at present is through the python command line
> option -O.

Yes, and that was the intent.

> But since I normally do unit and system testing in Python interactive
> mode, that would require exiting and re-executing python every time I
> wanted to change the debug setting, or else have two separate sessions
> running, one with the -O switch set and one without.
> And that's just plain silly.

Use your own vrbl(s).  __debug__ exists for a different purpose.

> Can anyone explain to me why this change, to make __debug__ read only,
> is necessary or beneficial in some way?

Because assignment to __debug__ was never intended, and, as above, that
assignment under -O "doesn't work" keeps surprising people, despite that
its -O behavior was a key design goal.

> Or am I misinterpreting GvR's statement that "assignment to
> __debug__ ... will become illegal in 2.2."

Nope, he meant it.  Starting in 2.1, you'll get a Syntaxwarning msg whenever
you try to bind __debug__:

    SyntaxWarning: can not assign to __debug__

In 2.2, it will become a SyntaxError instead.

s/__debug__/DEBUG/g-ly y'rs  - tim





More information about the Python-list mailing list