Skip to main content
 首页 » 编程设计

python之断言 __debug__ == False 时断言

2025年05月04日16del

我做了一个简单的测试程序来测试分配给 __debug__ 使用 globals()["__debug__"] = value 的功能(__debug__ = value 是一个 SyntaxError)。它主要尝试引发 AssertionError 并打印是否引发了错误以及它是否在预期范围内。我这样做是因为我遇到了 __debug__ 在程序中更改的问题。

print("__debug__ is", __debug__) 
exp = ["(expected)", "(not expected)"] 
if __debug__: 
    exp = exp[::-1] 
try: 
    assert False 
    print("No AssertionError", exp[0]) 
except AssertionError: 
    print("AssertionError", exp[1]) 
exp = exp[::-1] 
globals()["__debug__"] = not __debug__ 
print("__debug__ is", __debug__) 
try: 
    assert False 
    print("No AssertionError", exp[0]) 
except AssertionError: 
    print("AssertionError", exp[1]) 

无论有没有 -O 标志,从命令提示符运行它都会产生意想不到的结果。

C:\Test>python assert.py 
__debug__ is True 
AssertionError (expected) 
__debug__ is False 
AssertionError (not expected) 
C:\Test>python -O assert.py 
__debug__ is False 
No AssertionError (expected) 
__debug__ is True 
No AssertionError (not expected) 

看起来 __debug__ 正在改变,但是 assert 实际上并没有检查它是否改变了。

请您参考如下方法:

您不应该更改 __debug__ 的值
正如here下的注释状态:

Note: The names None, False, True and __debug__ cannot be reassigned (assignments to them, even as an attribute name, raise SyntaxError), so they can be considered “true” constants

发生这种情况的原因是因为 __debug__ 不 在运行时评估,而 -O 命令行标志是(在编译时).另见 Runtime vs Compile time .

虽然您可以通过 hack globals()["__debug__"] 更改 __debug__ 的值,但它什么都不做,因为 assert expression1, expression2 并不真的检查__debug__ 的值。提供 -O 标志将 False 分配给 __debug__ 并删除所有断言语句。也就是说,assert 语句由 -O 标志删除,不是 __debug__ 变量。

您可以使用 dis() 中的 dis() 看到这一点。使用以下代码:

import dis 
dis.dis("assert False") 

没有-O标志(path\to\file>python file.py):

  1           0 LOAD_CONST               0 (False) 
              3 POP_JUMP_IF_TRUE        12 
              6 LOAD_GLOBAL              0 (AssertionError) 
              9 RAISE_VARARGS            1 
        >>   12 LOAD_CONST               1 (None) 
             15 RETURN_VALUE 

使用 -O 标志(path\to\file>python -O file.py):

  1           0 LOAD_CONST               0 (None) 
              3 RETURN_VALUE 

如您所见,assert 语句基本上已从代码中删除。带有 -O 标记的第 0 到 3 行与没有标记的第 12 到 15 行相同。它没有在哪里检查 __debug__ 的值。