import datetime
import functools
import heapq
import inspect
import logging
import random
import time
import weakref
from eventlet.semaphore import Semaphore
from service.globaldef import Consts
logger = logging.getLogger(__name__)
def _argdict(f, args, kwargs):
argnames, _args, _kwargs, defaults = inspect.getargspec(f)
argdict = {}
if defaults:
k = len(argnames) - len(defaults)
argdict.update(dict(zip(argnames[k:], defaults)))
if args:
argdict.update(dict(zip(argnames[:len(args)], args)))
argdict.update(kwargs)
if len(argdict) < len(argnames):
raise Exception("require %d args, but get %d" %
(len(argnames), len(argdict)))
return argdict
class CacheEntry(object):
def __init__(self, end_ts=0, val=None):
self.end_ts = end_ts
self.val = val
class MyQueue(object):
def __init__(self, maxsize=0):
self.queue = []
self.maxsize = maxsize
self.semaphore = Semaphore()
def append(self, priority, data):
x = None
with self.semaphore:
if self.maxsize and len(self.queue) >= self.maxsize:
x = heapq.heappop(self.queue)
heapq.heappush(self.queue, (priority, data))
print 'append: ', (priority, data), ',heappop:', x
class LocalCache(object):
_CACHE = weakref.WeakValueDictionary()
STRONG_REF = MyQueue(10000)
NOT_FOUND = CacheEntry()
@classmethod
def get_key(cls, func, key_fmt, args, kwargs):
if key_fmt is None:
cache_key = "%s.%s.%s" % (
Consts.SVR_NAME, func.__module__, func.__name__)
else:
arg_dict = _argdict(func, args, kwargs)
cache_key = key_fmt.format(**arg_dict)
return cache_key
@classmethod
def get_cache(cls, key):
return cls._CACHE.get(key, cls.NOT_FOUND)
@classmethod
def set_cache(cls, key, val, expire):
now = time.time()
cache_entry = CacheEntry(now + expire, val)
cls._CACHE[key] = cache_entry
cls.STRONG_REF.append(cache_entry.end_ts, cache_entry)
@classmethod
def cacheable(cls, key_fmt=None, expire=30):
"""
本地缓存 ,注意 key_fmt 如果 是 None 那么不会把 方法的参数作为 key
:param key_fmt: key 可添加动态参数
:param expire: 单位 秒 缓存 多少秒
:return:
"""
def decorate(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
cache_key = cls.get_key(func, key_fmt, args, kwargs)
ts = time.time()
cache_entry = cls.get_cache(cache_key)
if ts <= cache_entry.end_ts:
logger.info('locacache hint,cache_key:%s' % cache_key)
return cache_entry.val
else:
ret_val = func(*args, **kwargs)
cls.set_cache(cache_key, ret_val, expire)
return ret_val
return wrapper
return decorate
if __name__ == '__main__':
x = MyQueue(2)
for i in range(10):
x.append(random.randint(0, 100), 'x')
python本地缓存
最新推荐文章于 2024-04-19 14:00:00 发布