Home > Software engineering >  How to ignore function arguments with cachetools ttl_cache
How to ignore function arguments with cachetools ttl_cache

Time:12-31

I'm exploiting the cachetools @ttl_cache decorator (not @cached). I need to ignore some params in the cache key. E.g,.

@ttl_cache(maxsize=1024, ttl=600)
def my_func(foo, ignore_bar, ignore_baz):
    # do stuff

Working that way, I get this:

>>> my_func("foo", "ignore_bar", "ignore_baz")         # cache miss
>>> my_func("foo", "ignore_bar", "ignore_baz")         # cache hit
>>> my_func("foo", "ignore_bar_bar", "ignore_baz_baz") # cache miss!

What I need:

>>> my_func("foo", "ignore_bar", "ignore_baz")         # cache miss
>>> my_func("foo", "ignore_bar", "ignore_baz")         # cache hit
>>> my_func("foo", "ignore_bar_bar", "ignore_baz_baz") # cache hit!!!!!

Is there a way to get that using @ttl_cache?

CodePudding user response:

I haven't used cachetools, but I've looked at the docs out of interest. Apparently, there's no built-in way. If you really need this functionality, I can suggest a hack like the following:

class PackedArgs(tuple):
    def __hash__(self):
        return hash(self[0])

    def __eq__(self, other):
        if isinstance(other, self.__class__):
            return self[0] == other[0]
        else:
            return NotImplemented

def pack_args(func):
    def inner(packed_args):
        return func(*packed_args)
    return inner

def unpack_args(func):
    def inner(*args):
        return func(PackedArgs(args))
    return inner

@unpack_args
@ttl_cache(maxsize=1024, ttl=600)
@pack_args
def my_func(foo, ignore_bar, ignore_baz):
    # do stuff

Essentially: "pack" your function's arguments to a single tuple-like object that hashes as it's 0th element and causes @ttl_cache to behave like you need. Then, "unpack" them to restore the normal interface and avoid actually having to pass this one big argument when calling.

Please note that this is just a (very hacky) concept, I haven't tested this code at all. It probably won't work as is.

By the way, your requirement sounds interesting. You can submit it to cachetools as a feauture request and link this thread. I can imagine it being implemented as something like a key= kwarg lambda, similar to builtin sort's.

CodePudding user response:

Well, that's exactly what @cached and its custom key argument are for, so I wonder why you want to use @ttl_cache for this:

from cachetools import TTLCache, cached
from cachetools.keys import hashkey

def mykey(foo, ignore_bar, ignore_baz):
    return hashkey(foo)

@cached(cache=TTLCache(maxsize=1024, ttl=600), key=mykey)
def my_func(foo, ignore_bar, ignore_baz):
    # do stuff
  • Related