尽管__debug__为真,条件__debug__语句没有执行
简短版本
我正在调试一段代码,这段代码会检查一个叫 __debug__
的值,如果它是 True,就会执行一些代码。
if __debug__:
<stuff happens>
问题是,尽管 __debug__
看起来是 True,但“事情”就是没有发生。
详细版本 / 细节
为了检查这个,我在函数执行时把几个变量的值打印到一个文件里,特别是 __debug__
。我使用了以下的方式来实现这个。 (我用 os.open
是因为在这个模块里 open
已经被定义了。)
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)
让我最困惑的那段代码看起来是这样的:
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__))
而输出文件的内容是这样的:
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
前面三条语句(第82-84行)是我想到的所有检查 __debug__
是否“真实”的方法,所有这三种方式都表明 __debug__
是 True。同样,把 __debug__
转换成布尔值后再进行 if
判断(第88行)也按预期工作。第90行是一个简单的检查。
在 __debug__
的工作方式上,我是不是遗漏了什么,导致了这个问题?
注意: 我在处理 python-ldap
模块中的 _ldap_function_call
函数时发现了这个问题。只有在使用 IIS 时我才会遇到这个错误 - 在 Django 的开发服务器上一切正常。
1 个回答
如果你重新绑定了 __debug__
,可能会导致和这个问题一模一样的情况。
这是因为 __debug__
有点神奇。在模块编译的时候,处理字面量的代码也会处理这些神奇的常量,比如 ...
、None
、True
、False
和 __debug__
。(你可以看看,比如在expr_constant
这个地方。)
如果你用 dis
来查看你的代码的字节码,你会发现 if __debug__:
这样的语句要么完全被移除,要么用 LOAD_CONST
来加载编译时的 debug
常量,而 if bool(__debug__):
这样的语句则用 LOAD_GLOBAL
来加载 __debug__
的值。
当然,这两个值是保证相同的……除非你重新绑定了 __debug__
。在大约 2.3 版本的时候,直接写 __debug__ = False
就变成不合法了。在 2.7 和 3.0 版本中,绑定任何名为 __debug__
的属性都是不合法的,这意味着你不能再像 sys.modules[__name__].__debug__ = False
这样做了。不过你仍然可以做,比如 globals()['__debug__'] = False
。
无论如何,你都会得到相同的效果:
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"
这会打印出:
debug
bool
debug2
同样的情况也适用于当你用 python -O
运行代码时将其设置为 True。