V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
l4ever
V2EX  ›  Python

flask_caching 之 memoize 谜团

  •  
  •   l4ever · 2019-12-25 17:29:59 +08:00 · 3283 次点击
    这是一个创建于 1825 天前的主题,其中的信息可能已经有所发展或是发生改变。
        # 缓存设置
        CACHE_TYPE = 'simple'
        # CACHE_TYPE = 'filesystem'
        # CACHE_THRESHOLD = 5000
        CACHE_DIR = './tmp/'
        CACHE_DEFAULT_TIMEOUT = 60 * 60 * 1
    
        @cache.memoize(timeout=7200)
        def get_token(self, secret):
            uri = f'{self.host}/gettoken?corpid={self.corpid}&corpsecret={secret}'
            res = http(uri) # 这里用 http 去统一处理. 
            token = res.get('access_token', '')
    
            if not token:
                errcode = res.get('errcode', '')
                errmsg = res.get('errmsg', '')
                current_app.logger.error(f'get_token error. errcode: {errcode}; errmsg:{errmsg}.')
            else:
                current_app.logger.debug(f'get_token success. token: {token}')
            return token
    
    

    上例这样写没错吧? 问题是我在 http 请求函数里面打日志 每次都会进行请求

    from flask_caching import Cache
    from flask import Flask
    
    app = Flask(__name__)
    
    cache = Cache()
    cache.init_app(app, config={
        "CACHE_TYPE": "simple"
    })
    
    def ab(dd):
        print('ab')
        return dd
    
    @cache.memoize(timeout=30)
    def sum_data(a, b):
        c = int(a) + int(b)
        c = ab(c)
        return c
    
    
    @app.route('/')
    def hello_world():
        return str(sum_data(1, 2))
    
    
    if __name__ == "__main__":
        app.run(debug=True)
    
    

    一气之下, 自己用官方的例子发现并不会重复输出 ab 有点费解. 哪里出错了.

    8 条回复    2019-12-27 10:39:40 +08:00
    timonwong
        1
    timonwong  
       2019-12-25 17:51:12 +08:00
    KEY: instance method, the "self" varies
    tmackan
        2
    tmackan  
       2019-12-26 09:49:28 +08:00
    @timonwong 有道理
    tmackan
        3
    tmackan  
       2019-12-26 09:50:38 +08:00
    本地缓存都是根据参数,然后 hash 生成 redis 的 key,所以 self 这种场景不实用,参数不固定
    tmackan
        4
    tmackan  
       2019-12-26 09:53:04 +08:00
    ```
    def memoize(obj):
    """
    Local cache of the function return value
    """
    cache = obj.cache = {}

    @functools.wraps(obj)
    def memoizer(*args, **kwargs):
    key = str(args) + str(kwargs)
    if key not in cache:
    cache[key] = obj(*args, **kwargs)
    return cache[key]
    return memoizer
    ```
    tmackan
        5
    tmackan  
       2019-12-26 09:53:19 +08:00
    def memoize(obj):
    """
    Local cache of the function return value
    """
    cache = obj.cache = {}

    @functools.wraps(obj)
    def memoizer(*args, **kwargs):
    key = str(args) + str(kwargs)
    if key not in cache:
    cache[key] = obj(*args, **kwargs)
    return cache[key]
    return memoizer
    limboMu
        6
    limboMu  
       2019-12-26 15:16:39 +08:00
    @tmackan 刚刚看完源码,作者对装饰方法的时候做了特殊处理,你要保障 get_id(self)的结果是一致的就好了
    “”“
    def get_id(obj):
    return getattr(obj, "__caching_id__", repr)(obj)
    ”“”
    tmackan
        7
    tmackan  
       2019-12-26 20:08:48 +08:00
    class CacheProperty(object):
    """
    Decorator that converts a method with a single self argument into a
    property cached on the instance.

    Optional ``name`` argument allows you to make cached properties of other
    methods. (e.g. url = cached_property(get_absolute_url, name='url') )
    """
    def __init__(self, func, name=None):
    self.func = func
    self.__doc__ = getattr(func, '__doc__')
    self.name = name or func.__name__

    def __get__(self, instance, type=None):
    if instance is None:
    return self
    res = instance.__dict__[self.name] = self.func(instance)
    return res

    class A(object):
    @CacheProperty
    def create(self, id):
    return
    lolizeppelin
        8
    lolizeppelin  
       2019-12-27 10:39:40 +08:00
    处理 key generator

    args = compat.inspect_getargspec(fn)
    has_self = args[0] and args[0][0] in ('self', 'cls')
    if has_self:
    args = args[1:]


    或者直接用 dogpile
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3143 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 13:36 · PVG 21:36 · LAX 05:36 · JFK 08:36
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.