User documentation
Developer documentation
PyContracts overhead in production and in testing¶
In production, all checks can be disabled using the function contracts.disable_all()
.
All checks can also be disabled via the DISABLE_CONTRACTS
environment variable. If the variable is defined, then checks are disabled and cannot be enabled via contracts.enable_all()
.
Overhead when disabled¶
The performance in disabled mode depends on whether contracts.disable_all()
is called before or after the decorated function is loaded.
If disable_all()
is called before, then the decorator gets ignored and the overhead is 0. Example:
contracts.disable_all()
@contract(x='int,>=0', returns='int,>=1')
def f(x):
return x + 1
f(0) # no overhead
If disable_all()
is called after, then there is some overhead, because PyContracts will call the function as f(*args,**kwargs)
, which has some overhead. Example:
@contract(x='int,>=0', returns='int,>=1')
def f(x):
return x + 1
contracts.disable_all()
f(0) # some overhead
Performance hit when enabled¶
I haven’t done any rigorous benchmarking, but PyContract’s performance hit depends mainly on two factors:
PyContracts calls
inspect
methods to associate arguments to arguments names. This takes a surprising amount of time and probably there is a smarter way to do it.The time to check the contract for each argument. This depends on the complexity of the contract.
Each contract is parsed only once and then represented as a syntactic tree. For example, the representation of
int,>0
is:python -c "import contracts; print '%r' % contracts.parse('int,>=0')" And([CheckType(int), CheckOrder(None,'>=',SimpleRValue(0))])
Python being Python, there’s some overhead for calling object methods in the contract tree.
User documentation