__debug__ http://stackoverflow.com/questions/15305688

eryk sun eryksun at gmail.com
Wed Nov 16 10:22:21 EST 2016


On Wed, Nov 16, 2016 at 8:39 AM, Steven D'Aprano
<steve+comp.lang.python at pearwood.info> wrote:
> On Wednesday 16 November 2016 16:21, Veek M wrote:
>
>> Trying to make sense of that article. My understanding of debug was
>> simple:
>> 1. __debug__ is always True, unless -O or -OO
>> 2. 'if' is optimized out when True and the expr is inlined.
>>
>> So what does he mean by:
>>
>> 1. 'If you rebind __debug__, it can cause symptoms'
>
> What he means is, "I didn't test this code before running it, and I am wrong."
>
> You cannot rebind __debug__.
>
>>>> __debug__ = False
>   File "<stdin>", line 1
> SyntaxError: can not assign to __debug__
>
>
> (That's Python 2.5 or better, and maybe even older than that.)

Andrew didn't assign directly to __debug__. He assigned to
sys.modules[__name__].__debug__, which is allowed prior to 2.7. Even
in later versions, as he pointed out, you can dynamically assign to
'__debug__' in a namespace dict.

For an expression containing __debug__, i.e. not simply an `if
__debug__` test, the compiler emits a LOAD_NAME operation (or
LOAD_GLOBAL in a function) to load the value on the stack and evaluate
the expression. Thus the builtins value may be shadowed by a local or
global value, or you can just modify builtins directly.

This inconsistency could be addressed by making __debug__ a static
symbol, which in CPython would always be determined by the value of
the C global variable Py_OptimizeFlag. In this case a code block would
reference a '__debug__' constant in its co_consts, defined at compile
time.

For example, this is the current inconsistent compile-time vs run-time
behavior, tested in 3.5:

    >>> import sys
    >>> sys.flags.optimize
    0
    >>> vars(sys.modules['builtins'])['__debug__'] = False

Compiling a simple `if __debug__` block depends on the value of Py_OptimizeFlag:

    >>> if __debug__: print('__debug__')
    ...
    __debug__

But evaluating an expression requires loading the dynamic value of __debug__:

    >>> if not __debug__: print('not __debug__')
    ...
    not __debug__

    >>> vars(sys.modules['builtins'])['__debug__'] = True
    >>> if not not __debug__: print('__debug__')
    ...
    __debug__

For `if __debug__` blocks, the compiler looks at the value of the C
global variable Py_OptimizeFlag:

    >>> import ctypes
    >>> Py_OptimizeFlag = ctypes.c_int.in_dll(
    ...     ctypes.pythonapi, 'Py_OptimizeFlag')

    >>> if __debug__: print('__debug__')
    ... else: print('not __debug__')
    ...
    __debug__

    >>> Py_OptimizeFlag.value = 1
    >>> if __debug__: print('__debug__')
    ... else: print('not __debug__')
    ...
    not __debug__

Off topic:
The text after the question ID in a Stack Overflow URL is optional, so
I removed it from the message title.



More information about the Python-list mailing list