Assertion
- The proper use of assertions is to inform developers about unrecoverable errors in a program.
- Assertions are not intended to signal expected error conditions.
- Assertions are meant to be internal self-checks for your program.
keep in mind that Python’s assert statement is a debugging aid, not a mechanism for handling run-time errors.
The goal of using assertions is to let developers find the likely root cause of a bug more quickly. An assertion error should NEVER be raised unless there’s a bug in your program.
Syntax
assert_stmt ::= "assert" expression1 ["," expression2]
expression1
is the condition we test- the optional
expression2
is an error message that’s displayed if the assertion fails.
At execution time, the Python interpreter transforms each assert state- ment into roughly the following sequence of statements:
if __debug__:
if not expression1:
raise AssertionError(expression2)
Before the assert condition is checked, there’s an additional check for the __debug__
global variable. It’s a built-in boolean flag that’s true under normal circumstances and false if optimizations are requested.
Two caveats when using asserts
Don’t Use Asserts for Data Validation
Assertions can be globally disabled3 with the -0
and -00
command line switches, as well as the PYTHONOPTIMIZE
environment variable in CPython!
$\rightarrow$ This turns any assert statement into a null-operation: the assertions simply get compiled away and won’t be evaluated 🤪, which means that none of the conditional expressions will be executed. As a side-effect, it becomes extremely dan- gerous to use assert statements as a quick and easy way to validate input data.
The solution to avoid this problem is: NEVER use assertions to do data validation. Instead, we could do our validation with regular if
-statements and raise validation exceptions if necessary
Example
❌ Don’t do
def delete_product(prod_id, user):
assert user.is_admin(), 'Must be admin'
assert store.has_product(prod_id), 'Unknown product'
store.get_product(prod_id).delete()
✅ Do
def delete_product(product_id, user):
if not user.is_admin():
raise AuthError('Must be admin to delete')
if not store.has_product(product_id):
raise ValueError('Unknown product id')
store.get_product(product_id).delete()
Asserts That Never Fail
When you pass a tuple as the first argument in an assert
statement, the assertion always evaluates as true
and therefore never fails.
For example, the following assertion will never fail:
assert(1 == 2, 'This should fail')
Reason is that non-empty tuples is always true
in Python.
A good countermeasure you can apply to prevent this syntax quirk from causing trouble is to use a code linter. Newer versions of Python 3 will also show a syntax warning for these dubious asserts.