I have a costly function that I want to cache using functools.lru_cache, but only under certain runtime conditions.
decorator-based, no problem:
from functools import lru_cache
@lru_cache(maxsize=32)
def myfunc(a, b):
return a * b
print(myfunc(1,2))
print(myfunc(1,2))
print(myfunc(1,3))
print(f"cache_info:{myfunc.cache_info()}")
output:
2
2
3
cache_info:CacheInfo(hits=1, misses=2, maxsize=32, currsize=2)
doesn't without @-based syntax
However, I run into problems when I try to declare the function first, then conditionally wrap it in lru_cache
, without using @decorator syntax.
from functools import lru_cache
def conditional_cached_func(a, b):
return a * b
some_system_dependent_value = True
if some_system_dependent_value:
cache_done = False
# I'm trying multiple calls to see what lru_cache expects
# only #3 works, but just so you don't replicate the other ones.
if not cache_done:
try:
conditional_cached_func = lru_cache(conditional_cached_func)
cache_done = True
print("#caching #1 worked")
except (Exception,) as e:
print(f"caching #1 error: {e}")
if not cache_done:
try:
conditional_cached_func = lru_cache(conditional_cached_func, maxsize=32)
cache_done = True
print("#caching #2 worked")
except (Exception,) as e:
print(f"caching #2 error: {e}")
if not cache_done:
try:
conditional_cached_func = lru_cache(32, conditional_cached_func)
cache_done = True
print("#caching #3 worked")
except (Exception,) as e:
print(f"caching #3 error: {e}")
#but in fact #3 doesn't work when called.
print(conditional_cached_func(2,2))
print(conditional_cached_func(2,2))
print(conditional_cached_func(2,3))
if some_system_dependent_value:
print(f"conditional_cache_info:{conditional_cached_func.cache_info()}")
output:
cache_info:CacheInfo(hits=1, misses=2, maxsize=32, currsize=2)
caching #1 error: Expected maxsize to be an integer or None
caching #2 error: lru_cache() got multiple values for argument 'maxsize'
#caching #3 worked
Traceback (most recent call last):
File "test_147_lrucache.py", line 56, in <module>
print(conditional_cached_func(2,2))
TypeError: decorating_function() takes 1 positional argument but 2 were given
I'm on Python 3.6, which I am mentioning as 3.8 apparently has tweaked some aspects of decorators that may be relevant.
Actually, it works under 3.8, with syntax #1
What do I need to do under 3.6?
#caching #1 worked
4
4
6
conditional_cache_info:CacheInfo(hits=1, misses=2, maxsize=128, currsize=2)
If you're really, really, curious... this is hitting a mostly read-only database. While running tests, the result of my costly function to introspect the database can be assumed to be static and won't change. Under live conditions, those results can change at any time, but the users will pretty much never look at them.