Python has an option to compile the optimized bytecode and create the respective .pyo
files by using the options -O
and -OO
.
During this, these basic optimizations are done:
- All the
assert
statements are removed - All docstrings are removed (when
-OO
is selected) - Value of the
__debug__
built-in variable is set toFalse
Now, if someone never intends to run the optimized bytecode, they can ignore this issue. But, it is still recommended not to have it in non-test files.
A better way for internal self-checks is to explicitly check and raise respective Error
using an if
statement.
Here’s an example to show why the issue is raised for assert
statement in non-test files:
Let’s call this script foo.py
import sys
assert len(sys.argv) == 5
print("Argument variables are: ", args)
This is supposed to work fine if the length of the argument variables is 5. But, would raise an AssertionError
otherwise.
When the optimized bytecode is compiled using:
python -O -m compileall foo.py
A new file foo.pyo
is created.
Here’s the traceback when we run both the file:
foo.py:
$ python foo.py 1 2 3 4 5
Traceback (most recent call last):
File "foo.py", line 4, in <module>
assert len(sys.argv) == 5
AssertionError
foo.pyo:
$ python foo.pyo 1 2 3 4 5 6
sys.args are: ['foo.pyo', '1', '2', '3', '4', '5', '6']
Note: python -O foo.py
would work the same way as of running the .pyo
file.
Here, all the internal self-checks using the assert
statements are removed, as we can see.
Therefore, there’s a chance for an application to behave strangely in this case.