An assert statement checks an internal assumption when assertions are enabled; it is not a stable input-validation boundary.
Python assert versus input validation: optimized execution changes the contract
Operation contract
The owned child program runs twice through the same executable, once normally and once with -O. Its assertion rejects a negative amount in the first run and disappears in the second. The application validator uses an explicit conditional and raises ValueError in both modes. Nothing received is executed: the child source is a fixed teaching string. Keep the assertion for a developer invariant only after establishing the input contract.
Failure and ownership boundary
An assertion expression can have side effects that disappear under optimization. That includes logging, mutation and calls needed for correctness. Neither annotations nor assertions replace the accepted-value checks in Python type conversion: parsing success is not field validity and Python typing reference: annotations, structural checks and runtime validation differ. Tests can use assertions; public application rejection must not depend on interpreter optimization flags.
Working program
import subprocess
import sys
owned_source = """
def assertion_only(amount):
assert amount >= 0
return amount
def validated(amount):
if type(amount) is not int or amount < 0:
raise ValueError("nonnegative exact integer required")
return amount
for operation in (assertion_only, validated):
try:
print(operation(-25))
except (AssertionError, ValueError) as failure:
print(type(failure).__name__)
"""
for optimized in (False, True):
command = [sys.executable, "-I"] + (["-O"] if optimized else [])
output = subprocess.run(command + ["-c", owned_source], capture_output=True,
text=True, check=True, timeout=5).stdout.splitlines()
print("optimized:", optimized, output)Output
optimized: False ['AssertionError', 'ValueError']
optimized: True ['-25', 'ValueError']Costs and limits
The scalar validator has bounded work for this input. Child startup is a process cost, not a benchmark of assertion performance. A conditional check still needs the right domain rule; checking only a sign would accept Boolean values and unrelated numeric types.
Common Mistakes
- Do not put required work inside an assertion expression.
- Do not use -O-dependent checks to enforce a public input schema.
Connected lessons
Python exceptions: translate an input error without hiding its cause, Python type conversion: parsing success is not field validity, Python compatibility checks: parse syntax and execute contracts as separate evidence.
