2016-11-18 37 views
1

目前,我使用functools'lru_cache来处理我的缓存功能。问题是缓存的大小从来不会增长到足以使用LRU(由于该函数从不接受参数)。相反,该函数在被调用时会打开一个特定的URL并返回其内容。有没有办法使用生存时间装饰器缓存Python 3.5定义?

有没有一种方法可以指定'生存时间'缓存,在一定时间/特定数量的调用后,它会刷新其缓存?

+0

我不明白你的缓存规则。函数是否多次返回一件事?如果这个url没有参数,你怎么知道潜在的返回值是本地缓存的? – tdelaney

+0

我问过这个问题,因为听起来你根本就不想要lru缓存。这听起来像你想在一段时间内使用url返回值,然后刷新它。你能以某种方式确认吗? – tdelaney

+0

@tdelaney所以我从URL中获取的资源偶尔会更新(如每几个小时一次)。我希望函数缓存函数的返回值,并且在网页更新的情况下每更新一次缓存设置几个小时。 – EndenDragon

回答

2

我不知道一个装饰的,但你可以跟踪你得到的页面和更新的最后一次需要。如果这是一个单线程的应用程序,它可以是简单的

_cached_page = '' 
_cached_page_time = 0 

def get_page(): 
    global _cached_page, _cached_page_time 
    now = time.time() 
    # invalidate in 1 hour 
    if not _cached_page or now - _cached_page_time > 60 * 60: 
     _cached_page = get_the_page_here() 
     _cached_page_time = time.time() 
    return _cached_page 

你也可以在后台使用计时器来使页面老化。您需要使用锁来控制访问,但这也会使缓存在多线程程序中可用。

_cached_page = '' 
_cached_page_lock = threading.Lock() 

def _invalidate_page(): 
    global _cached_page 
    with _cached_page_lock: 
     _cached_page = '' 

def get_page(): 
    global _cached_page 
    with _cached_page_lock: 
     if not _cached_page: 
      _cached_page = get_the_page_here() 
      # invalidate in 1 hour 
      threading.Timer(60*60, _invalidate_page) 
     return _cached_page 

最后,服务器可能在http头中包含一个Expires: ...字段。根据服务的写入情况,这可以很好地反映页面可以被缓存多久。

1

functools.lru_cache函数接受maxsize参数,该参数将结果保存到最近的调用maxsize

您可以通过调用装饰函数的cache_info属性来检查该属性。

如果要完全刷新缓存,则应通过计算缓存调用的数量并在缓存达到最大大小时重置缓存来手动实施现金对象。

from functools import wraps 


class Mycache(object): 
    def __init__(self, maxcount): 
     self.count = 0 
     self.maxcount = maxcount 
     self.cache = {} 

    def __call__(self, func): 

     @wraps(func) 
     def wrapped(*args): 
      self.count += 1 
      if self.count > self.maxcount: 
       self.cache = {} 
       self.count = 0 
       result = self.cache[args] = func(*args) 
      else: 
       try: 
        result = self.cache[args] 
       except KeyError: 
        result = self.cache[args] = func(*args) 
      return result 
     return wrapped 

演示:

@Mycache(3) 
def a(arg): 
    print("arg is : {}".format(arg)) 
    return arg ** 2 

print(a(4)) 
print(a(4)) 
print(a(4)) 
print(a(4)) 
print(a(3)) 
print(a(4)) 

输出:

arg is : 4 
16 
16 
16 
arg is : 4 
16 
arg is : 3 
9 
16 
+0

OP说这个函数不带参数....对我来说听起来像lru不是他想要的,不管它的参数化如何。 – tdelaney

+0

@tdelaney我不知道这一点,但我认为可能通过实现一个自定义的memoizer装饰器一些其他的方式。 – Kasramvd

相关问题