Using assert outside tests

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 to False

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.

4 Likes