1

我试图缓存一个函数的返回值,以防它不是无。

在下面的示例中,缓存 someFunction 的结果是有意义的,以防它设法从 some-url 获取数据一小时。

如果无法获取数据,将结果缓存一个小时(或更长时间)是没有意义的,但可能会缓存 5 分钟(因此 some-domain.com 的服务器有一些时间来恢复)

def _cachekey(method, self, lang):
    return (lang, time.time() // (60 * 60))

@ram.cache(_cachekey)
def someFunction(self, lang='en'):
    data = urllib2.urlopen('http://some-url.com/data.txt', timeout=10).read()

    except socket.timeout:
        data = None
    except urllib2.URLError:
        data = None

    return expensive_compute(data)

调用method(self, lang)_cachekey 没有多大意义。

4

2 回答 2

1

在这种情况下,您不应该概括“返回为无”,因为装饰器缓存的结果只能取决于输入值。

相反,您应该在函数内部构建缓存机制,而不是依赖装饰器。

然后这变成了一个通用的非 Plone 特定的 Python 问题,如何缓存值。

这是一个如何使用 RAMCache 构建手动缓存的示例:

https://developer.plone.org/performance/ramcache.html#using-custom-ram-cache

于 2013-09-24T22:31:52.813 回答
1

由于此代码对于评论来说太长了,因此我将其发布在这里,希望对其他人有所帮助:

#initialize cache
from zope.app.cache import ram
my_cache = ram.RAMCache()
my_cache.update(maxAge=3600, maxEntries=20)
_marker = object()


def _cachekey(lang):
    return (lang, time.time() // (60 * 60))


def someFunction(self, lang='en'):

    cached_result = my_cache.query(_cacheKey(lang), _marker)

    if cached_result is _marker:
        #not found, download, compute and add to cache
        data = urllib2.urlopen('http://some-url.com/data.txt', timeout=10).read()
        except socket.timeout:
            data = None
        except urllib2.URLError:
            data = None

        if data is not None:
            #cache computed value for 1 hr
            computed = expensive_compute(data)
            my_cache.set(data, (lang, time.time() // (60 * 60) )
        else:
            # allow download server to recover 5 minutes instead of trying to download on every page load
            computed = None
            my_cache.set(None, (lang, time.time() // (60 * 5) )

        return computed


    return cached_result
于 2013-09-25T14:06:11.643 回答