经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » Python » 查看文章
10分钟掌握Python缓存
来源:cnblogs  作者:程序员世杰  时间:2024/6/28 9:34:59  对本文有异议

全文速览

  • python的不同缓存组件的使用场景和使用样例
  • cachetools的使用

项目背景

代码检查项目,需要存储每一步检查的中间结果,最终把结果汇总并写入文件中

在中间结果的存储中

  • 可以使用context进行上下文的传递,但是整体对代码改动比较大,违背了开闭原则
  • 也可以利用缓存存储,处理完成之后再统一读缓存并写入文件

在权衡了不同方案后,我决定采用缓存来存储中间结果。接下来,我将探讨 Python 中可用缓存组件。

python缓存分类

决定选择缓存,那么python中都有哪些类型的缓存呢?

1. 使用内存缓存(如 functools.lru_cache

这是最简单的一种缓存方法,适用于小规模的数据缓存。使用 functools.lru_cache 可以对函数结果进行缓存。

  1. from functools import lru_cache
  2. @lru_cache(maxsize=128)
  3. def expensive_function(param1, param2):
  4. # 进行一些耗时的操作
  5. return result

2. 使用本地文件缓存(如 diskcache

如果缓存的数据较大,或者需要跨进程共享缓存,可以使用文件系统缓存库,例如 diskcache

  1. import diskcache as dc
  2. cache = dc.Cache('/tmp/mycache')
  3. @cache.memoize(expire=3600)
  4. def expensive_function(param1, param2):
  5. # 进行一些耗时的操作
  6. return result

3. 使用分布式缓存(如 Redis)

对于需要跨多个应用实例共享缓存的数据,可以使用 Redis 这样的分布式缓存系统。

  1. import redis
  2. import pickle
  3. r = redis.StrictRedis(host='localhost', port=6379, db=0)
  4. def expensive_function(param1, param2):
  5. key = f"{param1}_{param2}"
  6. cached_result = r.get(key)
  7. if cached_result:
  8. return pickle.loads(cached_result)
  9. result = # 进行一些耗时的操作
  10. r.set(key, pickle.dumps(result), ex=3600) # 设置缓存过期时间为1小时
  11. return result

总结

如果只是简单的小规模缓存,lru_cache 足够;如果需要持久化或分布式缓存,可以考虑使用 diskcache 或 Redis;如果使用了 Web 框架,使用框架自带的缓存功能会更方便。

python内存缓存分类

兼顾速度和成本以及实现的复杂度,最终决定使用内存缓存,在 Python 中,内存缓存组件有许多选择,每种都有其特定的优点和适用场景。以下是一些常见的内存缓存组件:

1. functools.lru_cache

lru_cache 是 Python 标准库中的一个装饰器,用于缓存函数的返回结果,基于最近最少使用(LRU)策略。

  1. from functools import lru_cache
  2. @lru_cache(maxsize=128)
  3. def expensive_function(param1, param2):
  4. # 进行一些耗时的操作
  5. return result

2. cachetools

cachetools 是一个第三方库,提供了多种缓存策略,包括 LRU、LFU、TTL(基于时间的缓存)等。

  1. from cachetools import LRUCache, cached
  2. cache = LRUCache(maxsize=100)
  3. @cached(cache)
  4. def expensive_function(param1, param2):
  5. # 进行一些耗时的操作
  6. return result

3. django.core.cache

如果使用 Django 框架,Django 自带了缓存框架,支持多种缓存后端,包括内存缓存。

settings.py 中配置内存缓存:

  1. CACHES = {
  2. 'default': {
  3. 'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
  4. 'LOCATION': 'unique-snowflake',
  5. }
  6. }

4. Flask-Caching

如果使用 Flask 框架,Flask-Caching 插件可以方便地实现内存缓存。

  1. from flask import Flask
  2. from flask_caching import Cache
  3. app = Flask(__name__)
  4. cache = Cache(app, config={'CACHE_TYPE': 'simple'})
  5. @app.route('/expensive')
  6. @cache.cached(timeout=60)
  7. def expensive_function():
  8. # 进行一些耗时的操作
  9. return result

5. requests_cache

requests_cache 是一个专门用于缓存 HTTP 请求的库,支持多种缓存后端,包括内存缓存。

  1. import requests
  2. import requests_cache
  3. requests_cache.install_cache('demo_cache', backend='memory', expire_after=3600)
  4. response = requests.get('https://api.example.com/data')

6. dogpile.cache

dogpile.cache 是一个更高级的缓存库,提供了灵活的缓存后端和缓存失效策略。

  1. from dogpile.cache import make_region
  2. region = make_region().configure(
  3. 'dogpile.cache.memory',
  4. expiration_time=3600
  5. )
  6. @region.cache_on_arguments()
  7. def expensive_function(param1, param2):
  8. # 进行一些耗时的操作
  9. return result

7. joblib.Memory

joblib.Memory 常用于科学计算和数据处理领域,用于缓存函数的计算结果。

  1. from joblib import Memory
  2. memory = Memory(location='/tmp/joblib_cache', verbose=0)
  3. @memory.cache
  4. def expensive_function(param1, param2):
  5. # 进行一些耗时的操作
  6. return result

总结

根据具体需求和使用场景选择合适的内存缓存组件。对于简单的缓存需求,可以使用 functools.lru_cachecachetools。对于 Web 应用,django.core.cacheFlask-Caching 是不错的选择。对于 HTTP 请求缓存,可以使用 requests_cache。对于科学计算,joblib.Memory 是一个好选择。

cachetools使用

我的项目是一个命令行执行的项目,综合考量最终决定选择cachetools

  1. 安装 cachetools
  1. pip install cachetools
  1. 实现缓存工具类
  1. from cachetools import LRUCache
  2. from cachetools import Cache
  3. from siada.cr.logger.logger import logger
  4. class CacheUtils:
  5. """
  6. 缓存工具类
  7. """
  8. def __init__(self, cache: Cache = None):
  9. self.cache = cache if cache else LRUCache(maxsize=100)
  10. def get_value(self, cache_key: str):
  11. value = self.cache.get(cache_key, None)
  12. if value is not None:
  13. logger.info(f"Cache hit for key: {cache_key}")
  14. else:
  15. logger.info(f"Cache miss for key: {cache_key}")
  16. return value
  17. def set_key_value(self, cache_key: str, value):
  18. self.cache[cache_key] = value
  19. logger.info(f"Set cache key: {cache_key} with value: {value}")
  20. def set_key_list(self, cache_key: str, value):
  21. v = self.cache.get(cache_key, None)
  22. if v is not None:
  23. v.append(value)
  24. else:
  25. self.cache[cache_key] = [value]
  26. def clear_cache(self):
  27. self.cache.clear()
  28. # TODO 如果后续生成过程改为多线程并发,需考虑数据竞争问题
  29. cache = CacheUtils()

更多惊喜

我还将定期分享:

  • 最新互联网资讯:让你时刻掌握行业动态。

  • AI前沿新闻:紧跟技术潮流,不断提升自我。

  • 技术分享与职业发展:助你在职业生涯中走得更远、更稳。

  • 程序员生活趣事:让你在忙碌的工作之余找到共鸣与乐趣。

关注回复【1024】惊喜等你来拿!

点击查看惊喜

敬请关注【程序员世杰】

点击关注程序员世杰

原文链接:https://www.cnblogs.com/xieshijie/p/18268899

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号