__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