【问题标题】:plone.memoize cache depending on function's return valueplone.memoize 缓存取决于函数的返回值
【发布时间】:2013-09-24 10:00:43
【问题描述】:

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

在下面的示例中,缓存 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)

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

【问题讨论】:

    标签: plone memoization


    【解决方案1】:

    在这种情况下,您不应该将“return as None”一概而论,因为装饰器缓存的结果只能取决于输入值。

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

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

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

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

    【讨论】:

      【解决方案2】:

      由于此代码太长,无法发表评论,因此我将其发布在此处,希望对其他人有所帮助:

      #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
      

      【讨论】:

      猜你喜欢
      • 2019-06-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-30
      • 2011-10-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多