Reputation: 229291
How do I disable assertions in Python?
That is, if an assertion fails, I don't want it to throw an AssertionError
, but to keep going.
How do I do that?
Upvotes: 123
Views: 56923
Reputation: 394795
#How do I disable assertions in Python?
There are multiple approaches that affect a single process, the environment, or a single line of code.
I demonstrate each.
Using the -O
flag (capital O) disables all assert statements in a process.
For example:
$ python -Oc "assert False"
$ python -c "assert False"
Traceback (most recent call last):
File "<string>", line 1, in <module>
AssertionError
Note that by disable I mean it also does not execute the expression that follows it:
$ python -Oc "assert 1/0"
$ python -c "assert 1/0"
Traceback (most recent call last):
File "<string>", line 1, in <module>
ZeroDivisionError: integer division or modulo by zero
You can use an environment variable to set this flag as well.
This will affect every process that uses or inherits the environment.
E.g., in Windows, setting and then clearing the environment variable:
C:\>python -c "assert False"
Traceback (most recent call last):
File "<string>", line 1, in <module>
AssertionError
C:\>SET PYTHONOPTIMIZE=TRUE
C:\>python -c "assert False"
C:\>SET PYTHONOPTIMIZE=
C:\>python -c "assert False"
Traceback (most recent call last):
File "<string>", line 1, in <module>
AssertionError
Same in Unix (using set and unset for respective functionality)
You continue your question:
if an assertion fails, I don't want it to throw an AssertionError, but to keep going.
You can either ensure control flow does not reach the assertion, for example:
if False:
assert False, "we know this fails, but we don't get here"
or if you want the assert expression to be exercised then you can catch the assertion error:
try:
assert False, "this code runs, fails, and the exception is caught"
except AssertionError as e:
print(repr(e))
which prints:
AssertionError('this code runs, fails, and the exception is caught')
and you'll keep going from the point you handled the AssertionError
.
From the assert
documentation:
An assert statement like this:
assert expression #, optional_message
Is equivalent to
if __debug__: if not expression: raise AssertionError #(optional_message)
And,
the built-in variable
__debug__
isTrue
under normal circumstances,False
when optimization is requested (command line option-O
).
and further
Assignments to
__debug__
are illegal. The value for the built-in variable is determined when the interpreter starts.
From the usage docs:
Turn on basic optimizations. This changes the filename extension for compiled (bytecode) files from .pyc to .pyo. See also PYTHONOPTIMIZE.
and
If this is set to a non-empty string it is equivalent to specifying the
-O
option. If set to an integer, it is equivalent to specifying-O
multiple times.
Upvotes: 132
Reputation: 14636
Both of the two answers already given are valid (call Python with either -O
or -OO
on the command line).
From the Python documentation, here is the difference between them:
-O
Turn on basic optimizations. This changes the filename extension
for compiled (bytecode) files from .pyc to .pyo.
-OO
Discard docstrings in addition to the -O
optimizations.
To check if assertions are enabled or disabled, see the value of __debug__
.
Upvotes: 19
Reputation: 11464
You should NOT disable assertions. They catch unanticipated errors when attention is elsewhere. See Rule 5 in "The power of ten" (DOI, Wikipedia).
Write raise
statements, instead of assert
statements:
if x_is_broken():
raise RuntimeError('`x` is broken.')
The raise
statements remain present, whatever the optimization options with which Python is run. Also, using raise
statements enables specifying a type of exception different than AssertionError
. This is very useful for users. Moreover, just writing a raise
statement prompts to ask oneself whether AssertionError
is the right choice there.
In addition, when writing a raise
statement, we are lead to write an informative message, for example raise AssertionError('An error occurred with `x`.')
. Writing an error message is possible in an assert
statement (e.g., assert x, 'An error occurred with `x`.'
, and parentheses can be used for messages written over multiple lines), however, it can be forgotten. In contrast, raise AssertionError(....)
requires that ....
be filled (and the form raise AssertionError
is unusual and not recommended).
When writing error messages, it is remarkable how many further coding errors will be revealed.
Sidenote: computationally expensive assertion checks can be run only when requested. One way is:
import logging
log = logging.getLogger(__name__)
if log.getEffectiveLevel() < logging.DEBUG:
if not check_expensive_property(x):
raise RuntimeError('`x` is broken.')
Upvotes: 3
Reputation: 258128
Call Python with the -O flag:
test.py:
assert False
print('Done')
Output:
C:\temp\py>C:\Python26\python.exe test.py
Traceback (most recent call last):
File "test.py", line 1, in <module>
assert(False)
AssertionError
C:\temp\py>C:\Python26\python.exe -O test.py
Done
Upvotes: 63