Redis获取和设置d

2024-04-29 13:32:07 发布

您现在位置:Python中文网/ 问答频道 /正文

目前正在研究python和redis。我以烧瓶为框架,在设计蓝图。在

为了让我的API使用redis实现缓存,我尝试了Flask cacheredis simple cache。 缺点是Flask-Cache即使更改了函数的参数,也会保存该函数。每个函数只保存一次。 根据redis-simple-cache,它将其密钥保存为SimpleCache-<key name>,这在我这方面并不可取。在

所以我的问题是,如何创建一个decorator来保存和检索或者检查是否存在特定键的键。 我知道一个节省装饰是可能的。但是是否可以使用检索或检查装饰器??如果我错了,请纠正我。谢谢您。在


Tags: key函数redis框架apiflaskcache参数
2条回答

你似乎没有仔细阅读Flask-Cache documentation。缓存不会忽略参数,并且缓存键是可自定义的。项目提供的装饰器已经为您提供了所需的功能。在

Caching View Functions section

This decorator will use request.path by default for the cache_key.

因此,默认的缓存键是request.path,但是您可以指定一个不同的键。{eem>使函数成为默认的参数。在

^{} decorator documentation

cached(timeout=None, key_prefix='view/%s', unless=None)

By default the cache key is view/request.path. You are able to use this decorator with any function by changing the key_prefix. If the token %s is located within the key_prefix then it will replace that with request.path. You are able to use this decorator with any function by changing the key_prefix.

以及

key_prefix[...] Can optionally be a callable which takes no arguments but returns a string that will be used as the cache_key.

因此,您可以将key_prefix设置为一个函数,它将被调用(不带参数)以生成密钥。在

此外:

The returned decorated function now has three function attributes assigned to it. These attributes are readable/writable:

[...]

make_cache_key
A function used in generating the cache_key used.

传递此函数的参数与传递视图函数的参数相同。总之,这允许您生成所需的任何缓存键;要么使用key_prefix并从request或{}或其他源中提取更多信息,要么分配给view_function.make_cache_key并访问view函数接收的相同参数。在

然后是^{} decorator

memoize(timeout=None, make_name=None, unless=None)

Use this to cache the result of a function, taking its arguments into account in the cache key.

所以这个修饰符完全基于传递给函数的参数来缓存返回值。它也支持make_cache_key函数。在

我使用了这两个decorator使googleappengineflask项目的规模达到每月两位数的数百万次浏览量,并将结果存储在googlememcached结构中。使用Redis只需要设置一个配置选项。在

您可以使用这个cache decorator,您创建的缓存对象必须是flask缓存对象,而不是django对象,即应该支持缓存.get以及缓存.set方法,这是非常灵活的,基于您想要创建缓存键的方式,即

  • 基于传递给方法的参数
  • 在什么情况下缓存/不缓存结果
  • 即使kwarg顺序发生更改,也要使用相同的缓存,即我的方法(a=1,b=2)和我的方法(b=2,a=1)调用使用相同的缓存。在

““

__author__ = 'Dhruv Pathak'


import cPickle
import logging
import time
from functools import wraps
from django.conf import settings
import traceback

"""following imports are from datautils.py in this repo, datautils
also contains many other useful data utility methods/classes
"""
from datautils import mDict, mList, get_nested_ordered_dict, nested_path_get

"""following import is specific to django framework, and can be altered
based on what type of caching library your code uses"""
from django.core.cache import cache, caches


logger = logging.getLogger(__name__)

def cache_result(cache_key=None, cache_kwarg_keys=None, seconds=900, cache_filter=lambda x: True, cache_setup = "default"):
    def set_cache(f):
        @wraps(f)
        def x(*args, **kwargs):
            if settings.USE_CACHE is not True:
                result = f(*args, **kwargs)
                return result
            try:
                # cache_conn should be a cache object supporting get,set methods
                # can be from python-memcached, pylibmc, django, django-redis-cache, django-redis etc
                cache_conn = caches[cache_setup]
            except Exception, e:
                result = f(*args, **kwargs)
                return result
            final_cache_key = generate_cache_key_for_method(f, kwargs, args, cache_kwarg_keys, cache_key)
            try:
                result = cache_conn.get(final_cache_key)
            except Exception, e:
                result = None
                if settings.DEBUG is True:
                    raise
                else:
                    logger.exception("Cache get failed,k::{0},ex::{1},ex::{2}".format(final_cache_key, str(e), traceback.format_exc()))

            if result is not None and cache_filter(result) is False:
                result = None
                logger.debug("Cache had invalid result:{0},not returned".format(result))

            if result is None: # result not in cache
                result = f(*args, **kwargs)
                if isinstance(result, (mDict, mList)):
                    result.ot = int(time.time())
                if cache_filter(result) is True:
                    try:
                        cache_conn.set(final_cache_key, result, seconds)
                    except Exception, e:
                        if settings.DEBUG is True:
                            raise
                        else:
                            logger.exception("Cache set failed,k::{0},ex::{1},ex::{2},dt::{3}".format(final_cache_key, str(e), traceback.format_exc(), str(result)[0:100],))
                #else:
                #    logger.debug("Result :{0} failed,not cached".format(result))

            else: # result was from cache
                if isinstance(result, (mDict, mList)):
                    result.src = "CACHE_{0}".format(cache_setup)
            return result
        return x
    return set_cache


def generate_cache_key_for_method(method, method_kwargs, method_args, cache_kwarg_keys=None, cache_key=None):
    if cache_key is None:
        if cache_kwarg_keys is not None and len(cache_kwarg_keys) > 0:
            if len(method_args) > 0:
                raise Exception("cache_kwarg_keys mode needs set kwargs,args should be empty")

            method_kwargs = get_nested_ordered_dict(method_kwargs)
            cache_kwarg_values = [nested_path_get(method_kwargs, path_str=kwarg_key, strict=False) for kwarg_key in cache_kwarg_keys]
            if any([kwarg_value is not None for kwarg_value in cache_kwarg_values]) is False:
                raise Exception("all cache kwarg keys values are not set")

            final_cache_key = "{0}::{1}::{2}".format(str(method.__module__), str(method.__name__), hash(cPickle.dumps(cache_kwarg_values)))
        else:
            final_cache_key = "{0}::{1}".format(str(method.__module__), str(method.__name__))
            final_cache_key += "::{0}".format(str(hash(cPickle.dumps(method_args, 0)))) if len(method_args) > 0 else ''
            final_cache_key += "::{0}".format(str(hash(cPickle.dumps(method_kwargs, 0)))) if len(method_kwargs) > 0 else ''
    else:
        final_cache_key = "{0}::{1}::{2}".format(method.__module__, method.__name__, cache_key)

    return final_cache_key

2-3个实用程序方法从这个file导入到同一个repo中,您可以将它们放在同一个文件中。在

相关问题 更多 >