If you rebind __debug__
, it can cause symptoms exactly like this.
This is because __debug__
is somewhat magical. During module compilation, the same code that handles literals also handles the magic constants ...
, None
, True
, False
, and __debug__
. (See, for example, expr_constant
.)
If you run dis
on your code to dump out the bytecode, you'll see that if __debug__:
statements are either removed entirely, or use LOAD_CONST
to load the compile-time debug
constant, while if bool(__debug__):
statements use LOAD_GLOBAL
to load the value of __debug__
.
Of course these are guaranteed to be the same… unless you rebind __debug__
. Somewhere around 2.3, it became illegal to just write __debug__ = False
. In 2.7 and 3.0, it became illegal to bind any attribute named __debug__
, which means you can no longer do things like sys.modules[__name__].__debug__ = False
. But you can still do, e.g., globals()['__debug__'] = False
.
And either way, you get the same effect:
if __debug__:
print "debug"
if bool(__debug__):
print "bool"
import sys
sys.modules[__name__].__debug__ = False
if __debug__:
print "debug2"
if bool(__debug__):
print "bool2"
This prints out:
debug
bool
debug2
And likewise for code that sets it to True when run with python -O
.