Flask-caching---flask缓存插件

Flask-caching 是flask 的一款缓存插件,它是从Flask-cache fork而来,一直在更新,而Flask-cache则已经很多年没有更新过了,如果想在flask项目里使用缓存,一定要使用Flask-caching, 安装方式如下

pip install -U flask-caching

官方文档地址: https://flask-caching.readthedocs.io/en/latest/

1. 初始化缓存插件

import time
from flask import Flask
from flask_caching import Cache

app = Flask(__name__)

cache_config = {
    "CACHE_TYPE": "SimpleCache",    # 缓存类型
    "CACHE_DEFAULT_TIMEOUT": 300    # 默认缓存过期时间
}

app.config.from_mapping(cache_config)
cache = Cache(app)

CACHE_TYPE 我使用的是SimpleCache, 这将使用本地python目录做缓存,在flask-caching 2.0 中将被移除。

2. 对视图返回结果进行缓存

@app.route("/top_score/<int:id>")
@cache.cached(timeout=10)
def top_score(id):
    return {'id': id, 'score': int(time.time())}

if __name__ == '__main__':
    app.run(port=5555, debug=True)

从第一次请求的时间算起,10秒钟内,再次发起的请求将使用上一次缓存的结果。缓存的key 是请求的path路径,因此,id不同,得到的结果也就不同,但相同的id,10秒钟内得到的都是缓存的结果

对视图进行缓存时,一定要放在@app.route装饰器的前面。

3. 缓存普通函数

flask-caching 也可以用来缓存普通的函数

@cache.cached(timeout=10)
def get_top_score(id):
    return {'id': id, 'score': int(time.time())}

@app.route("/top_score/<int:id>")
def top_score(id):
    return get_top_score(id)

虽然cache.cached 装饰的是get_top_score函数,但是,缓存的key依然是基于请求的path生成的,因此不同的id有不同的缓存。

但这仅限于你不指定key_prefix的情况,key_prefix参数值默认是 view/%s , 在底层处理时,flask-caching会找到本次请求的path 填充%s 的部分,但如果你指定了key_prefix 且不包含/%s ,那么就将基于被装饰的函数名称生成缓存的key

@cache.cached(timeout=10, key_prefix='top_score')
def get_top_score(id):
    return {'id': id, 'score': int(time.time())}

@app.route("/top_score/<int:id>")
def top_score(id):
    return get_top_score(id)

现在访问http://127.0.0.1:5555/top_score/4,然后访问http://127.0.0.1:5555/top_score/1, 将得到相同的内容。

4. 使用memoize装饰器

在第3小结中,如果指定了key_prefix参数,那么缓存无法根据参数分别进行缓存,缓存的key里不包含实际传入的参数,这种情况下,可以使用memoize装饰器

@cache.memoize(timeout=10)
def get_top_score(id):
    return {'id': id, 'score': int(time.time())}

使用memoize装饰器,它会默认将被装饰函数的参数加入到缓存的key中,这样,参数不同,其缓存结果也会不同。

5. 使用文件做缓存 FileSystemCache

import time
from flask import Flask
from flask_caching import Cache

app = Flask(__name__)

cache_config = {
    "CACHE_TYPE": "FileSystemCache",    # 缓存类型
    "CACHE_DIR": "./cache"
}

app.config.from_mapping(cache_config)
cache = Cache(app)

@cache.memoize(timeout=10)
def get_top_score(id):
    return {'id': id, 'score': int(time.time())}

@app.route("/top_score/<int:id>")
def top_score(id):
    return get_top_score(id)


if __name__ == '__main__':
    app.run(port=5555)

指定CACHE_TYPE 为 FileSystemCache, 并通过CACHE_DIR 设置缓存文件的存储位置,就可以在文件里缓存数据,相比于SimpleCache, 它的优势在于服务重启以后,缓存的数据仍然存在,但这样也只是适用于单点系统,如果服务是多点部署,就需要一个多点都能访问的存储介质,flask-caching也支持redis.

6. 使用redis做缓存

import time
from flask import Flask
from flask_caching import Cache

app = Flask(__name__)

cache_config = {
    "CACHE_TYPE": "RedisCache",    # 缓存类型
    "CACHE_REDIS_URL": "redis://:123456@localhost:6379/2"
}

app.config.from_mapping(cache_config)
cache = Cache(app)

@cache.memoize(timeout=10)
def get_top_score(id):
    return {'id': id, 'score': int(time.time())}

@app.route("/top_score/<int:id>")
def top_score(id):
    return get_top_score(id)


if __name__ == '__main__':
    app.run(port=5555)

redis是专门用来做缓存的,flask-caching 使用redis来做缓存介质相比于其他方案更快更稳定,因此推荐你使用这种方法。

7. 直接使用cache 对象

如果你有额外的想要缓存的数据,而不是缓存函数的返回结果,可以直接使用cache对象的set方法和get方法分别进行缓存和读取缓存的操作。

import time,json
from flask import Flask
from flask_caching import Cache

app = Flask(__name__)

cache_config = {
    "CACHE_TYPE": "RedisCache",    # 缓存类型
    "CACHE_REDIS_URL": "redis://:123456@localhost:6379/2"
}

app.config.from_mapping(cache_config)
cache = Cache(app)


def get_top_score(id):
    return {'id': id, 'score': int(time.time())}

@app.route("/top_score/<int:id>")
def top_score(id):
    key = str(id)
    score = cache.get(key)      # 先从缓存中获取
    print(score)
    if score is None:           # 没有缓存,调用get_top_score 函数获取
        score = get_top_score(id)
        cache.set(key, score, timeout=10)       # 过期时间设置为10秒

    return score


if __name__ == '__main__':
    app.run(port=5555)

8. 清除缓存

flask-caching 提供了清除缓存的办法,在app被创建且完成cache初始化以后,可以在不运行flask服务的条件下清除缓存

if __name__ == '__main__':
    with app.app_context():
        cache.clear()

扫描关注, 与我技术互动

QQ交流群: 211426309

加入知识星球, 每天收获更多精彩内容

分享日常研究的python技术和遇到的问题及解决方案