Search code examples
pythonpython-3.xflaskflask-cache

Flask cache some data but not all


I have a function that I am trying to calculate the run time duration. when I use the Flask cache, it won't go into the function and won't calculate the duration.

@app.route('/', methods=['get'])
@cache.cached(timeout=60)
def request_process_duration():
    start = time.time()
    for i in range(5):
        time.sleep(1)
    duration = time.time() - start
    return jsonify(duration)

This function output was 5 for 60 seconds (cache timeout) I want to get an output of 5 in the first run, and then for the next 60 seconds much lower output.


Solution

  • when I use the Flask cache, it won't go into the function and won't calculate the duration.

    As you may already understand this is because only the return value of that function is cached.

    One approach to solve this might be to create your own decorator to time the function.

    So initialize the app, and configure the cache:

    from flask import Flask, jsonify
    import time 
    
    app = Flask(__name__)
    
    from flask_caching import Cache
    
    config = {
        "DEBUG": True,          # some Flask specific configs
        "CACHE_TYPE": "simple", # Flask-Caching related configs
        "CACHE_DEFAULT_TIMEOUT": 300
    }
    
    app.config.from_mapping(config)
    cache = Cache(app)
    

    Then define a decorator. This one will print the output in seconds:

    def timeit(method):
        def timed(*args, **kw):
            ts = time.time()
            result = method(*args, **kw)
            te = time.time()        
            print ((te-ts), 'seconds')
            return result
        return timed
    

    Finally decorate the function you wish to time. The decorator lines must be placed in this order:

    @app.route('/', methods=['get'])
    @timeit
    @cache.cached(timeout=60)
    def request_process_duration():
        for i in range(5):
            time.sleep(1)
        return {'status':'success'}
    

    When tested with two subsequent requests, this gives the ouput at the server console:

    4.977460145950317 seconds
    172.17.0.1 - - [07/Aug/2020 14:57:04] "GET / HTTP/1.1" 200 -
    0.00011014938354492188 seconds
    172.17.0.1 - - [07/Aug/2020 14:57:05] "GET / HTTP/1.1" 200 -
    

    The only problem with this approach is that the calculated time is only available within the decorator itself. I had searched on how to pass this back to the decorated function which doesn't appear to help because the end time is calculated after the return value of method is assigned to result.

    Perhaps you could solve this by writing that value to a log or a database, if required. Sorry this is as far as my skills take me :)