断言 __debug__ == False 时断言
assert asserting when __debug__ == False
我做了一个简单的测试程序来测试使用 globals()["__debug__"] = value
分配给 __debug__
的功能(__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__
.
的值
我做了一个简单的测试程序来测试使用 globals()["__debug__"] = value
分配给 __debug__
的功能(__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, raiseSyntaxError
), 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__
.