Python in-memory cache with time to live

后端 未结 8 1544
后悔当初
后悔当初 2020-12-04 23:24

I have multiple threads running the same process that need to be able to to notify each other that something should not be worked on for the next n seconds its not the end o

8条回答
  •  夕颜
    夕颜 (楼主)
    2020-12-05 00:13

    I absolutely love the idea from @iutinvg, I just wanted to take it a little further. Decouple it from having to know to pass the ttl and just make it a decorator so you don't have to think about it. If you have django, py3 and don't feel like pip installing any dependencies, try this out.

    import time
    from django.utils.functional import lazy
    from functools import lru_cache, partial, update_wrapper
    
    
    def lru_cache_time(seconds, maxsize=None):
        """
        Adds time aware caching to lru_cache
        """
        def wrapper(func):
            # Lazy function that makes sure the lru_cache() invalidate after X secs
            ttl_hash = lazy(lambda: round(time.time() / seconds), int)()
            
            @lru_cache(maxsize)
            def time_aware(__ttl, *args, **kwargs):
                """
                Main wrapper, note that the first argument ttl is not passed down. 
                This is because no function should bother to know this that 
                this is here.
                """
                def wrapping(*args, **kwargs):
                    return func(*args, **kwargs)
                return wrapping(*args, **kwargs)
            return update_wrapper(partial(time_aware, ttl_hash), func)
        return wrapper
    
    
    @lru_cache_time(seconds=10)
    def meaning_of_life():
        """
        This message should show up if you call help().
        """
        print('this better only show up once!')
        return 42
    
    
    @lru_cache_time(seconds=10)
    def multiply(a, b):
        """
        This message should show up if you call help().
        """
        print('this better only show up once!')
        return a * b
        
    # This is a test, prints a `.` for every second, there should be 10s 
    # between each "this better only show up once!" *2 because of the two functions.
    for _ in range(20):
        meaning_of_life()
        multiply(50, 99991)
        print('.')
        time.sleep(1)
    

提交回复
热议问题