Python 注解方式實現(xiàn)緩存數(shù)據(jù)詳解
背景
每次加載數(shù)據(jù)都要重新Load,想通過加入的注解方式開發(fā)緩存機(jī)制,每次緩存不用寫代碼了
缺點:目前僅支持一個返回值,雖然能弄成字典,但是已經(jīng)滿足個人需求,沒動力改(狗頭)。
拿來即用
新建文件 Cache.py
class Cache:
def __init__(self, cache_path='.', nocache=False):
self.cache_path = cache_path
self.cache = not nocache
def __call__(self, func):
@wraps(func)
def wrapper(*args, **kwargs):
s = f'{func.__code__.co_filename}.{func.__name__}'
s += ','.join(list(args[1:]) + [f'{k}={v}' for k, v in kwargs.items()])
md5 = hashlib.md5()
md5.update(s.encode('utf-8'))
cache_file = f'{self.cache_path}/{md5.hexdigest()}'
if self.cache and os.path.exists(cache_file):
print('Loading from cache')
return pickle.load(open(cache_file, 'rb'))
else:
if not os.path.exists(self.cache_path):
os.makedirs(self.cache_path)
data = func(*args, **kwargs)
pickle.dump(data, file=open(cache_file, 'wb'))
print(f'Dump finished {cache_file}')
return data
return wrapper
from .Cache import Cache
@Cache(root_path, nocache=True)
def load_data(self, inpath):
return 'Wula~a~a~!'
實踐過程
第一次,來個簡單的繼承父類
class Cache(object):
def __init__(self, cache_path=None):
self.cache_path = cache_path if cache_path else '.'
self.cache_path = f'{self.cache_path}/cache'
self.data = self.load_cache()
def load_cache(self):
if os.path.exists(self.cache_path):
print('Loading from cache')
return pickle.load(open(self.cache_path, 'rb'))
else:
return None
def save_cache(self):
pickle.dump(self.data, file=open(self.cache_path, 'wb'))
print(f'Dump finished {self.cache_path}')
class Filter4Analyzer(Cache):
def __init__(self, rootpath, datapath):
super().__init__(rootpath)
self.root_path = rootpath
if self.data is None:
self.data = self.load_data(datapath)
self.save_cache()
只要繼承Cache類就可以啦,但是有很多局限,例如只能指定某個參數(shù)被cache,例如還得在Filter4Analyzer里面寫保存的代碼。
下一步,python嵌套裝飾器來改善這個問題
from functools import wraps
import hashlib
def cached(cache_path):
def wrapperper(func):
@wraps(func)
def wrapper(*args, **kwargs):
s = f'{func.__code__.co_filename}.{func.__name__}' + ','.join(args[1:])
s += ','.join(list(args[1:]) + [f'{k}={v}' for k, v in kwargs.items()])
md5 = hashlib.md5()
md5.update(s.encode('utf-8'))
cache_file = f'{cache_path}/{md5.hexdigest()}' if cache_path else './cache'
if os.path.exists(cache_file):
print('Loading from cache')
return pickle.load(open(cache_file, 'rb'))
else:
if not os.path.exists(cache_path):
os.makedirs(cache_path)
data = func(*args, **kwargs)
pickle.dump(data, file=open(cache_file, 'wb'))
print(f'Dump finished {cache_file}')
return data
return wrapper
return wrapperper
class Tester:
@cached(cache_path='./workpath_test')
def test(self, data_path):
return ['hiahia']
通過裝飾器類簡化代碼
class Cache:
def __init__(self, cache_path='.', nocache=False):
self.cache_path = cache_path
self.cache = not nocache
def __call__(self, func):
@wraps(func)
def wrapper(*args, **kwargs):
s = f'{func.__code__.co_filename}.{func.__name__}'
s += ','.join(list(args[1:]) + [f'{k}={v}' for k, v in kwargs.items()])
md5 = hashlib.md5()
md5.update(s.encode('utf-8'))
cache_file = f'{self.cache_path}/{md5.hexdigest()}'
if self.cache and os.path.exists(cache_file):
print('Loading from cache')
return pickle.load(open(cache_file, 'rb'))
else:
if not os.path.exists(self.cache_path):
os.makedirs(self.cache_path)
data = func(*args, **kwargs)
pickle.dump(data, file=open(cache_file, 'wb'))
print(f'Dump finished {cache_file}')
return data
return wrapper
參考:
Python函數(shù)屬性和PyCodeObject
總結(jié)
本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
Python 搭建Web站點之Web服務(wù)器網(wǎng)關(guān)接口
本文是Python 搭建Web站點系列文章的第二篇,接上文,主要給大家來講述Web服務(wù)器網(wǎng)關(guān)接口WSGI的相關(guān)資料,非常詳細(xì),有需要的小伙伴可以參考下2016-11-11
python,Django實現(xiàn)的淘寶客登錄功能示例
這篇文章主要介紹了python,Django實現(xiàn)的淘寶客登錄功能,結(jié)合實例形式分析了Django框架基于淘寶接口的登錄功能相關(guān)操作技巧,需要的朋友可以參考下2019-06-06
python Tornado事件循環(huán)示例源碼解析
這篇文章主要為大家介紹了python Tornado事件循環(huán)示例源碼解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-09-09

