assert asserting when __debug__ == False
assert, debugging, python
Solution
You are not meant to change the value of __debug__ As the note under here states:
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
The reason this is happening is because `__debug__` is not evaluated at runtime, rather the `-O` command line flag is (At compile time). See also Runtime vs Compile time.
While you can change the value of `__debug__` through the hack `globals()["__debug__"]`, it does nothing, as the `assert expression1, expression2` doesn't really check for the value of `__debug__`. Supplying the `-O` flag assigns `False` to `__debug__` and removes all assert statements. That is to say, `assert` statements are removed by the `-O` flag, not the `__debug__` variable.
You can see this with `dis()` from `dis`. Using the following code:
import dis
dis.dis("assert False")
Without the `-O` flag (`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
With the `-O` flag (`path\to\file>python -O file.py`):
1 0 LOAD_CONST 0 (None)
3 RETURN_VALUE
As you can see, the `assert` statement is essentially removed from the code. Lines 0 to 3 with the `-O` flag are identical to lines 12 to 15 without. No where does it check for the value of `__debug__`.
Problem
I made a simple test program to test the functionality of assigning to `__debug__` using `globals()["__debug__"] = value` (`__debug__ = value` is a `SyntaxError`). It basically tries to raise an `AssertionError` and prints if the error was raised and whether or not it was expected. I did this as I ran in to issues with `__debug__` changing mid-program. ``` 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]) ``` It produces unexpected results when run from command prompt, with and without the `-O` flag. ``` 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) ``` It seems that `__debug__` is changing, but `assert` is not actually checking if it has.