Python 注解方式实现缓存数据详解

作者:liuxing93619 时间:2023-07-15 22:11:22 

背景

每次加载数据都要重新Load,想通过加入的注解方式开发缓存机制,每次缓存不用写代码了

缺点:目前仅支持一个返回值,虽然能弄成字典,但是已经满足个人需求,没动力改(狗头)。

拿来即用

新建文件 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类就可以啦,但是有很多局限,例如只能指定某个参数被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 函数装饰器

Python函数属性和PyCodeObject

来源:https://blog.csdn.net/liuxing93619/article/details/120837018

标签:Python,注解,实现,缓存
0
投稿

猜你喜欢

  • MySQL数据库高级数据操作之新增数据

    2024-01-18 17:46:38
  • js对象基础实例分析

    2023-09-03 12:07:56
  • 详细介绍Python中的set集合

    2023-07-26 07:35:03
  • 浅析Python数字类型和字符串类型的内置方法

    2022-06-16 12:57:24
  • 浅谈Webpack自动化构建实践指南

    2024-04-29 13:39:58
  • Python基础语法之变量与数据类型详解

    2022-06-21 17:52:36
  • 对python中执行DOS命令的3种方法总结

    2021-10-11 12:22:53
  • Python-split()函数实例用法讲解

    2023-12-12 07:13:20
  • PYTHON发送邮件YAGMAIL的简单实现解析

    2022-04-25 09:23:08
  • PHP容易被忽略而出错陷阱 数字与字符串比较

    2024-05-11 10:10:08
  • Python Django中间件,中间件函数,全局异常处理操作示例

    2022-02-18 20:21:40
  • MySQL的意向共享锁、意向排它锁和死锁

    2024-01-14 18:16:02
  • Go 值传递与引用传递的方法

    2023-06-25 03:11:11
  • Python绘制正余弦函数图像的方法

    2022-09-22 19:59:06
  • python爬取网站数据保存使用的方法

    2021-05-18 22:52:00
  • 基于Python实现简单学生管理系统

    2021-01-02 18:58:11
  • python从ftp获取文件并下载到本地

    2021-06-28 17:08:31
  • 网页中插入视频播放代码全集

    2007-10-22 17:48:00
  • python正则表达式实现自动化编程

    2022-01-08 12:24:33
  • CSS的学习应该注意学习方法

    2007-11-27 00:20:00
  • asp之家 网络编程 m.aspxhome.com