博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
使用烧瓶缓存
阅读量:2522 次
发布时间:2019-05-11

本文共 19785 字,大约阅读时间需要 65 分钟。

As a micro framework Flask does not have built-in cache functionality, however, there is werkzeug cache API and an excellent extension to provide its caching functionality to your Flask apps, that extension was created by @thadeusb and is very easy to implement and use.

但是,由于Flask不具有内置的缓存功能,因此它具有werkzeug缓存API和出色的扩展,可以为您的Flask应用程序提供其缓存功能,该扩展由@thadeusb创建,非常易于实现和使用。

安装 (installing)

In your env install it via PyPI (recommended)

在您的环境中通过PyPI安装(推荐)

pip install Flask-Cache  pip install Flask-Cache

You can also install it directly from source code if you need recent changes or bugfixes

如果您需要最近的更改或错误修正,也可以直接从源代码安装它

配置中 (Configuring)

There is a set of configuration keys you can put in your app settings, but the most important is the cache backend defined by the CACHE_TYPE key.

您可以在应用程序设置中放入一组配置键,但最重要的是由CACHE_TYPE键定义的缓存后端。

The cache type resolves to an import string which needs to be an object implementing the werkzeug cache api, but there is some aliases to the werkzeug.contrib.cache implementations

缓存类型解析为导入字符串,该导入字符串必须是实现werkzeug缓存api的对象,但是werkzeug.contrib.cache实现有一些别名

By default the CACHE_TYPE is Null which means that your app will have no cache, so you need to choose of the options below:

默认情况下,CACHE_TYPE为Null,这意味着您的应用程序将没有缓存,因此您需要选择以下选项:

  • null | No Cache – NullCache
  • simple | Will use in memory pickle and is recommended only for single process development server
  • memcached | Requires pylibmc or memcached and requires memcached configuration in settings
  • redis | Requires redis, werkzeug 0.7 and redis configuration in settings
  • filesystem | The same as simple but stores the pickle in a cache_dir
  • gaememcached | For Google AppEngine
  • saslmemcached | The same as memcached but for SASL – pylibmc required
  • | 无缓存-NullCache
  • 简单 将用在内存泡菜中,建议仅用于单进程开发服务器
  • memcached | 需要pylibmc或memcached,并且需要在设置中进行memcached配置
  • redis | 在设置中需要redis,werkzeug 0.7和redis配置
  • 文件系统 | 与简单相同,但是将泡菜存储在cache_dir中
  • gaememcached | 对于Google AppEngine
  • saslmemcached | 与memcached相同,但用于SASL –需要pylibmc


Full options and config variables are in

完整的选项和配置变量位于

一个简单的Flask应用 (A Simple Flask app)

a file named app.py

一个名为app.py的文件

import timefrom flask import Flaskapp = Flask(__name__)@app.route("/")def view():    return time.ctime()if __name__ == "__main__":    app.run(port=5000, debug=True, host='0.0.0.0')import timefrom flask import Flaskapp = Flask(__name__)@app.route("/")def view():    return time.ctime()if __name__ == "__main__":    app.run(port=5000, debug=True, host='0.0.0.0')

Run the above with python app.py and open in your browser and hit F5 (refresh) to see the current date and time.

使用python app.py运行以上python app.py然后在浏览器中打开 ,然后按F5(刷新)以查看当前日期和时间。

为视图启用Flask-Cache (Enabling Flask-Cache for views)

Now we want to enable caching on that small application to avoid the refresh of the current time (for this example we are using current time as return but imagine that it could be a large dataset or huge calculations)

现在,我们要在该小型应用程序上启用缓存以避免刷新当前时间(在本示例中,我们将当前时间用作返回值,但可以想象它可能是大型数据集或大量计算)

a file named cached_app.py

一个名为cached_app.py的文件

Run the above with python cached_app.py and open in your browser and hit F5 (refresh) to see that the current date and time is now cached for 5 minutes.

使用python cached_app.py运行以上python cached_app.py然后在浏览器中打开 ,然后按F5(刷新)以查看当前日期和时间已被缓存5分钟。

@cache.cached decorator takes the request.path for that view and use this as cache key, if for any reason you need a different key you can pass a key_prefix argument to the decorator. In this case if you pass a key_prefix containing the %s placeholder it will be replaced by the current request.path

@ cache.cached装饰器采用该视图的request.path并将其用作缓存键,如果出于任何原因需要其他键,则可以将key_prefix参数传递给装饰器。 在这种情况下,如果您传递包含%s占位符的key_prefix,它将被当前的request.path替换。

The above is the simplest and regular example of Flask app and the use of cache, but, if your app is designed using application factories, blueprints, class based views or views located in different modules you will need to use advanced approach.

上面是Flask应用程序和缓存使用的最简单且常规的示例,但是,如果您的应用程序是使用应用程序工厂,蓝图,基于类的视图或位于不同模块中的视图设计的,则需要使用高级方法。

缓存常规功能 (Caching regular functions)

The same cached decorator can be used to cache regular functions, but in this case you will need to specify the key_prefix argument, otherwise it will use the request.path which can lead to conflicts if you have many cached functions.

可以使用相同的缓存装饰器来缓存常规函数,但是在这种情况下,您需要指定key_prefix参数,否则它将使用request.path,如果您有很多缓存的函数,则可能导致冲突。

For this example we are going to use the this module and extract a random quote from the Zen of Python.

对于此示例,我们将使用this模块并从Python的Zen中提取随机引号。

A file named cached_function_app.py

名为cached_function_app.py的文件

import timeimport randomfrom this import s, dfrom string import translate, maketransfrom flask.ext.cache import Cachefrom flask import Flaskapp = Flask(__name__)app.config['CACHE_TYPE'] = 'simple'app.cache = Cache(app)@app.cache.cached(timeout=10, key_prefix="current_time")def get_current_time():    return time.ctime()def random_zen_quote():    """Pick a random quote from the Zen of Python"""     transtable = maketrans("".join(d.keys()), "".join(d.values()))    return random.choice(translate(s, transtable).split("n")[2:])@app.route("/")def zen():    return """    
  • It is cached: {cached}
  • It is not cached: {not_cached}
""".format( cached=get_current_time(), not_cached=random_zen_quote() )if __name__ == "__main__": app.run(debug=True, port=5000, host='0.0.0.0')import timeimport randomfrom this import s, dfrom string import translate, maketransfrom flask.ext.cache import Cachefrom flask import Flaskapp = Flask(__name__)app.config['CACHE_TYPE'] = 'simple'app.cache = Cache(app)@app.cache.cached(timeout=10, key_prefix="current_time")def get_current_time(): return time.ctime()def random_zen_quote(): """Pick a random quote from the Zen of Python""" transtable = maketrans("".join(d.keys()), "".join(d.values())) return random.choice(translate(s, transtable).split("n")[2:])@app.route("/")def zen(): return """
  • It is cached: {cached}
  • It is not cached: {not_cached}
""".format( cached=get_current_time(), not_cached=random_zen_quote() )if __name__ == "__main__": app.run(debug=True, port=5000, host='0.0.0.0')

Now running python cached_function_app.py and opening when hitting F5 to refresh you will see the current time cached for 5 minutes and the random quote updated, you can switch the cache just to see the efect.

现在运行python cached_function_app.py并在按F5刷新时打开 ,您将看到当前时间已缓存5分钟,并且随机报价已更新,您可以切换缓存以查看效果。

NOTE: Because we are importing the this module for the example, you will see the Zen quotes in your flask terminal, but there is no problem with this.

注意:因为我们正在导入示例的this模块,所以您将在flask终端中看到Zen引号,但是这样做没有问题。

缓存模块化视图 (Caching modular views)

Now an example when you have your app splitted in two or more files for better organization

现在是一个示例,其中将您的应用拆分为两个或更多文件以更好地组织

in a folder called app put 3 files__init__.py, app.py and views.py

在名为app的文件夹中,放入3个文件__init__.py . app.pyapp.pyviews.py

app/__init__.py is an empty file

app/__init__.py是一个空文件

app/views.py

app/views.py

import timeimport randomfrom this import s, dfrom string import translate, maketransdef get_current_time():    return time.ctime()def random_zen_quote():    transtable = maketrans("".join(d.keys()), "".join(d.values()))    return random.choice(translate(s, transtable).split("n")[2:])def zen_view():    return """    

Cached for 10 seconds!

  • {time}
  • {quote}
""".format( time=get_current_time(), quote=random_zen_quote() )import timeimport randomfrom this import s, dfrom string import translate, maketransdef get_current_time(): return time.ctime()def random_zen_quote(): transtable = maketrans("".join(d.keys()), "".join(d.values())) return random.choice(translate(s, transtable).split("n")[2:])def zen_view(): return """

Cached for 10 seconds!

  • {time}
  • {quote}
""".format( time=get_current_time(), quote=random_zen_quote() )

as you can see the above file defined view functions, as it it a separated file, to avoid circular imports we are not recommended to use @app.route neither @app.cache so this views will be app agnostic and we are going to register its url rules and caching in the main app file.

你可以看到定义视图功能上面的文件,因为它是一个分离的文件,避免循环进口,我们不建议使用@ app.route既不@ app.cache所以这个观点将是应用无关的 ,我们要登记其网址规则和缓存在主应用程序文件中。

That kind of structure is needed when your app has too many views and want a better organization.

当您的应用程序具有太多视图并希望有一个更好的组织时,就需要这种结构。

NOTE: For better organization the mostly recommended pattern is Blueprints which I will explain further.

注意:为了更好的组织,最推荐的模式是“蓝图”,我将进一步解释。

app/app.py

app/app.py

Now in the main app we need to import our views, explicitly decorate for caching and also register its urls.

现在,在主应用程序中,我们需要导入视图,显式装饰以进行缓存,并注册其url。

NOTE: You can also separate the cache instance in a different file for lazy initialization as we are going to see in the next example

注意:您也可以将缓存实例分离到另一个文件中以进行延迟初始化,如我们在下一个示例中将看到的那样

缓存蓝图视图 (Caching Blueprint views)

As mentioned before, the best pattern to follow in Flask applications is the Blueprint pattern which is a way to create separated ‘meta-apps’ that will be connected to your main application in the time of initialization, the problem here is that Blueprints are meant to be reusable by many different applications, so the delegation of cache control should be dynamized.

如前所述,在Flask应用程序中遵循的最佳模式是Blueprint模式,这是一种创建单独的“元应用程序”的方法,该应用程序将在初始化时连接到您的主应用程序,这里的问题是Blueprints意味着可以被许多不同的应用程序重用,因此应该动态化缓存控制的委托。

In order to avoid circular imports you will want to create your cache instance separate from your application instance (you may want to consider switching to the app factory module if you are building something more complex).

为了避免循环导入,您需要将缓存实例与应用程序实例分开创建(如果要构建更复杂的东西,则可能要考虑切换到应用程序工厂模块)。

Create a folder called blueprint_app with the following structure

使用以下结构创建一个名为blueprint_app的文件夹

cached_blueprint_app/├── app.py├── cache.py├── blueprints│   ├── __init__.py│   └── zen_blueprint.py└── __init__.pycached_blueprint_app/├── app.py├── cache.py├── blueprints│   ├── __init__.py│   └── zen_blueprint.py└── __init__.py

The cache.py

cache.py

we can create a dummy lazy cache instance, that will be initialized in the future when the view will be called. For that in the app we are going to reimport the same cache instance and call init_app method.

我们可以创建一个虚拟的惰性缓存实例,该实例将在以后调用视图时进行初始化。 为此,在应用程序中,我们将重新导入相同的缓存实例并调用init_app方法。

The basic blueprints/zen_blueprint.py

基本blueprints/zen_blueprint.py

import timeimport randomfrom this import s, dfrom string import translate, maketransfrom flask import Blueprintfrom cache import cachezen = Blueprint('zen', __name__)def get_current_time():    return time.ctime()def random_zen_quote():    transtable = maketrans("".join(d.keys()), "".join(d.values()))    return random.choice(translate(s, transtable).split("n")[2:])@zen.route("/")@cache.cached(timeout=20)def zen_view():    return """    

Cached for 20 seconds!

  • {time}
  • {quote}
""".format( time=get_current_time(), quote=random_zen_quote() )import timeimport randomfrom this import s, dfrom string import translate, maketransfrom flask import Blueprintfrom cache import cachezen = Blueprint('zen', __name__)def get_current_time(): return time.ctime()def random_zen_quote(): transtable = maketrans("".join(d.keys()), "".join(d.values())) return random.choice(translate(s, transtable).split("n")[2:])@zen.route("/")@cache.cached(timeout=20)def zen_view(): return """

Cached for 20 seconds!

  • {time}
  • {quote}
""".format( time=get_current_time(), quote=random_zen_quote() )

NOTE: In a real application you will want to modularize it separating the views, helpers etc and promoting your blueprint to a Python package.

注意:在实际的应用程序中,您将需要对其进行模块化,以分隔视图,助手等并将您的蓝图升级为Python包。

The main app.py

app.py

Notice that we created a dummy instance of cache in cache.py and then used that instance to decorate the blueprints views, then the cache was initialized in app.py with init_app method. That is possible because of the Flask initialization cycle and the excellent implementation in Flask-Cache extension that takes care of this case, if you plan to write yor own Flask extension take a look at the Flask-Cache source code.

请注意,我们在cache.py创建了一个缓存的虚拟实例,然后使用该实例来装饰蓝图视图,然后使用init_app方法在app.py中初始化了缓存。 由于Flask的初始化周期以及在这种情况下Flask-Cache扩展中出色的实现,使得这种情况成为可能,如果您打算编写自己的Flask扩展,请查看Flask-Cache源代码。

Run the application by calling python cached_blueprint_app/app.py and open to see the blueprint view cached for 20 seconds.

通过调用python cached_blueprint_app/app.py运行应用程序,然后打开以查看缓存了20秒的蓝图视图。

缓存方法视图 (Caching MethodView)

Lets use the same cached_blueprint_app example but turning the zen_view in to a MethodView

让我们使用相同的cached_blueprint_app示例,但将zen_view转到MethodView

Change your zen_blueprint.py to:

将您的zen_blueprint.py更改为:

import timeimport randomfrom this import s, dfrom string import translate, maketransfrom flask import Blueprintfrom flask.views import MethodViewfrom cache import cachezen = Blueprint('zen', __name__)class ZenView(MethodView):    @cache.cached(30)    def get(self):        return """        

Cached for 30 seconds!

  • {time}
  • {quote}
""".format( time=self.get_current_time(), quote=self.random_zen_quote() ) @staticmethod def get_current_time(): return time.ctime() @staticmethod def random_zen_quote(): transtable = maketrans("".join(d.keys()), "".join(d.values())) return random.choice(translate(s, transtable).split("n")[2:])zen.add_url_rule("/", view_func=ZenView.as_view('zen'))import timeimport randomfrom this import s, dfrom string import translate, maketransfrom flask import Blueprintfrom flask.views import MethodViewfrom cache import cachezen = Blueprint('zen', __name__)class ZenView(MethodView): @cache.cached(30) def get(self): return """

Cached for 30 seconds!

  • {time}
  • {quote}
""".format( time=self.get_current_time(), quote=self.random_zen_quote() ) @staticmethod def get_current_time(): return time.ctime() @staticmethod def random_zen_quote(): transtable = maketrans("".join(d.keys()), "".join(d.values())) return random.choice(translate(s, transtable).split("n")[2:])zen.add_url_rule("/", view_func=ZenView.as_view('zen'))

Method views maps HTTP method names as GET, POST, DELETE to the view methos as get, post, delete etc, So all we needed to do is to create a method called get and decorate it with @cache.cached decorator.

方法视图将HTTP方法名称(如GET,POST,DELETE)映射为视图方法(如get,post,delete等),因此我们所需要做的就是创建一个名为get的方法,并使用@cache.cached装饰器@cache.cached修饰。

NOTE: Due to the implicit self from the caller’s perspective you cannot use regular view decorators on the individual methods of the view however, Flask-Cache is one exception because its implementation allow the use of cached decorator in individual methods. Keep this in mind.

注意:由于从调用者的角度而言隐式的自我,您不能在视图的各个方法上使用常规视图装饰器,但是Flask-Cache是​​一个例外,因为其实现允许在各个方法中使用缓存的装饰器。 请记住这一点。

Alternativelly you may want to cache all the methods in a view, for that you can cache the dispatch_request method or even better you can decorate the whole view.

或者,您可能希望在视图中缓存所有方法,因为您可以缓存dispatch_request方法,甚至更好的是,您可以修饰整个视图。

缓存调度程序 (Caching the dispatcher)
缓存整个视图(推荐) (Caching the whole view (recommended))
zen = Blueprint('zen', __name__)class ZenView(MethodView):    ...cached_zen_view = cache.cached(timeout=50)(ZenView.as_view('zen'))zen.add_url_rule("/", view_func=cached_zen_view)zen = Blueprint('zen', __name__)class ZenView(MethodView):    ...cached_zen_view = cache.cached(timeout=50)(ZenView.as_view('zen'))zen.add_url_rule("/", view_func=cached_zen_view)

缓存模板块 (Caching template blocks)

Flask cache comes with a template tag able to cache template blocks, lets change our ZenView to use a Jinja2 template

Flask缓存带有一个模板标签,该标签能够缓存ZenView板块,让我们更改ZenView以使用Jinja2模板

in zen_blueprint.py

zen_blueprint.py

Now we need to create a template file in cached_blueprint_app/templates/zen.html

现在我们需要在cached_blueprint_app/templates/zen.html创建一个模板文件

Random Zen of Python

{
{get_random_quote()}}

Random Zen of Python

{
{get_random_quote()}}

Running the application with python cached_blueprint_app/app.py and opening you will see a random quote refreshed every time you push F5, lets cache it for 30 second.

使用python cached_blueprint_app/app.py运行应用程序并打开您每次按下F5都会看到刷新的随机报价,将其缓存30秒。

Change the zen.html template

更改zen.html模板

Now save the file and refresh to see the content cached for 30 seconds.

现在保存文件并刷新以查看缓存了30秒的内容。

使用备忘录装饰器缓存具有变体参数的函数和视图 (Caching functions and views with variant arguments using memoize decorator)

Sometimes yout views and functions receives arguments which can come from url mapping or directly to the function call, yiou may want to cache the view or funtion and use the arguments as keys to cache its different results, Flask-Cache has a different decorator for doing that.

有时,您的视图和函数接收到的参数可能来自网址映射或直接指向函数调用,您可能想缓存视图或函数,并使用这些参数作为键来缓存其不同的结果,Flask-Cache具有执行此操作的不同装饰器那。

NOTE: With functions that do not receive arguments, cached() and memoize() are effectively the same.

注意:对于不接收参数的函数,cached()和memoize()实际上是相同的。

Now with a simple application memoize_app.py

现在有了一个简单的应用程序memoize_app.py

import timefrom flask.ext.cache import Cachefrom flask import Flaskapp = Flask(__name__)app.config['CACHE_TYPE'] = 'simple'app.cache = Cache(app)@app.cache.memoize(timeout=5)def get_current_time_and_name(name):    return "%s - %s" % (name, time.ctime())@app.route("/
")def view(name): return get_current_time_and_name(name)if __name__ == "__main__": app.run(debug=True, port=5000, host='0.0.0.0')import timefrom flask.ext.cache import Cachefrom flask import Flaskapp = Flask(__name__)app.config['CACHE_TYPE'] = 'simple'app.cache = Cache(app)@app.cache.memoize(timeout=5)def get_current_time_and_name(name): return "%s - %s" % (name, time.ctime())@app.route("/
")def view(name): return get_current_time_and_name(name)if __name__ == "__main__": app.run(debug=True, port=5000, host='0.0.0.0')

Now run python memoize_app.py and open and note that the function will be cached for each different name you pass as argument in the url.

现在运行python memoize_app.py并打开 ,请注意,该函数将针对您作为url中的参数传递的每个不同名称进行缓存。

缓存任意对象 (Caching arbitrary objects)

There are some times when decorators cannot be used and you need to explicitly set or get some thing on the cache.

在某些情况下,不能使用装饰器,并且您需要显式设置或在缓存中获取某些东西。

Inside a view or a blueprint you can use current_app

在视图或蓝图内,您可以使用current_app

Or if using a separete cache instance you can do this directly

或者,如果使用单独的缓存实例,则可以直接执行此操作

from cache import cachedef function():    cached = cache.get('a_key')    if cached:        return cached    result = do_some_stuff()    cache.set('a_key', result, timeout=300)    return resultfrom cache import cachedef function():    cached = cache.get('a_key')    if cached:        return cached    result = do_some_stuff()    cache.set('a_key', result, timeout=300)    return result

清除缓存 (Clearing the cache)

You can create a script to clear the cache, or a function to use it when needed

您可以创建一个脚本来清除缓存,也可以创建一个函数以在需要时使用它

WARNING: Some backend implementation do not support completely clearing the case. Also, if you’re not using key prefix, some implementation (e.g. Redis) will flush the whole database. Make sure you’re not storing any other data in your caching database.

警告:某些后端实现不支持完全清除大小写。 另外,如果您不使用键前缀,则某些实现(例如Redis)将刷新整个数据库。 确保您没有在缓存数据库中存储任何其他数据。

翻译自:

转载地址:http://niqwd.baihongyu.com/

你可能感兴趣的文章
Android 关于悬浮窗权限的问题
查看>>
如何使用mysql
查看>>
android addRule()
查看>>
转:app store 注册账号生成证书上传app完整的教程
查看>>
dedecms 搬家流程
查看>>
POST提交大量数据,导致后面数据丢失
查看>>
To Do List
查看>>
增强一个对象的方法(继承、装饰者模式、动态代理)
查看>>
十一、多线程——8-线程池
查看>>
四、基础类库中的常用类——4-国际化与格式化
查看>>
Anders Hejlsberg访谈:Checked Exceptions的问题
查看>>
revit api 使用过滤器
查看>>
Qt532_字符编码转换
查看>>
设置网页自适应最大最小宽度,超过则隐藏
查看>>
几日工作记录
查看>>
const 和 static readonly 区别
查看>>
C#中发送消息给指定的窗口,以及接收消息(转载)
查看>>
Linux系统修改防火墙配置
查看>>
[winform]帮邻居写的一个小软件-沙盘治疗管理系统
查看>>
好玩的HTML5特效 转
查看>>