Conditional __debug__ statement not executed though __debug__ is True

debugging, iis-7, python, python-ldap

Solution

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`.

Problem

Short Version I have a section of code I'm debugging that checks the value of `__debug__` and executes some code if it is True. ``` if __debug__: <stuff happens> ``` The problem is that "stuff" never happens, even though `__debug__` appears to be True. Long Version / Details To check this, I am printing out the values of several variables, most notably `__debug__`, to a file as the function executes, using the following pattern. (I am using `os.open` because `open` is already defined in this module.) ``` try: myfile = os.open("test.txt", os.O_RDWR|os.O_CREAT|os.O_APPEND) # work + some print statements to check the value of __DEBUG__ finally: os.close(myfile) ``` The piece of code I'm most confused by looks like this: ``` os.write(myfile, "LINE %s | LDAP FUNCTION __DEBUG__: %s \n" %(sys._getframe(0).f_lineno, __debug__)) os.write(myfile, "LINE %s | LDAP FUNCTION __DEBUG__: %s \n" %(sys._getframe(0).f_lineno, type(__debug__))) os.write(myfile, "LINE %s | LDAP FUNCTION __DEBUG__: %s \n" %(sys._getframe(0).f_lineno, bool(__debug__))) if __debug__: os.write(myfile, "LINE %s | LDAP FUNCTION __DEBUG__: %s \n" %(sys._getframe(0).f_lineno, __debug__)) if bool(__debug__): os.write(myfile, "LINE %s | LDAP FUNCTION __DEBUG__: %s \n" %(sys._getframe(0).f_lineno, __debug__)) if True: os.write(myfile, "LINE %s | LDAP FUNCTION __DEBUG__: %s \n" %(sys._getframe(0).f_lineno, __debug__)) if __debug__: os.write(myfile, "LINE %s | LDAP FUNCTION __DEBUG__: %s \n" %(sys._getframe(0).f_lineno, __debug__)) ``` And the output file looks like this: ``` LINE 82 | LDAP FUNCTION __DEBUG__: True LINE 83 | LDAP FUNCTION __DEBUG__: <type 'bool'> LINE 84 | LDAP FUNCTION __DEBUG__: True LINE 88 | LDAP FUNCTION __DEBUG__: True LINE 90 | LDAP FUNCTION __DEBUG__: True ``` The first 3 statements (lines 82-84) are every way I could think of checking if `__debug__` is "truthy", and all 3 imply that `__debug__` is True. Similarly, casting `__debug__` as a boolean and then evaluating `if` (line 88) works as expected too. Line 90 is a silly sanity check. Is there anything I'm missing in the way `__debug__` works that may be causing this? Note: I found this while I was working through an error I am getting in the `_ldap_function_call` function in the `python-ldap` module. I only get this error when using IIS - everything works fine with Django's development server.

Original source