Python缓存神器cachetools:提高程序性能的利器,一文详解其缓存算法

简介: Python缓存神器cachetools:提高程序性能的利器,一文详解其缓存算法

前言


春山如黄,琬琰满枝,

烨烨清风,漫舞天地。


一、cachetools库简介以及详细使用


1-1、定义


cachetools : 是一个Python第三方库,提供了多种缓存算法的实现。缓存是一种用于临时存储计算结果的技术,以避免在后续计算中重复执行相同的计算。使用缓存可以提高应用程序的性能和响应速度。


1-2、多种缓存策略


cachetools 提供了以下常见的缓存策略

  • Least Recently Used (LRU): 这种策略会移除最近最少使用的条目。当需要为新的条目腾出空间时,最近最少使用的条目将被移除。这是一种常见的缓存策略,适用于大多数场景。
  • Most Recently Used (MRU): 这种策略会移除最近最常使用的条目。当需要为新的条目腾出空间时,最近最常使用的条目将被移除。这种策略适用于一些特殊场景,例如当最近访问的数据不太可能再次访问时。
  • Random Replacement (RR): 这种策略会随机移除一个条目。当需要为新的条目腾出空间时,随机选择一个条目进行移除。这种策略实现简单,但性能相对较差。
  • First-In-First-Out (FIFO): 这种策略会按照条目添加到缓存的顺序进行移除。先添加的条目先被移除。这种策略适用于一些特定场景,例如缓存的数据具有固定生命周期。


import cachetools
# 创建 LRU 缓存
lru_cache = cachetools.LRUCache(maxsize=100)
# 创建 MRU 缓存
mru_cache = cachetools.MostRecentlyUsed(maxsize=100)
# 创建 RR 缓存
rr_cache = cachetools.Random(maxsize=100)
# 创建 FIFO 缓存
fifo_cache = cachetools.FIFO(maxsize=100)


注意:

maxsize参数代表的是缓存中可以存储的最大条目数量,而不是字符数。在这个例子中,maxsize=10000表示缓存中最多可以存储10000个不同的键值对。

关于maxsize的最大值,理论上它取决于你的系统内存和应用程序的需求。实际使用中,你需要根据你的应用程序的内存使用情况和性能需求来决定一个合适的maxsize。通常,设置一个较大的maxsize可以提高缓存命中率,从而提高程序性能,但同时也会增加内存消耗。因此,在设置maxsize时,需要权衡程序性能和内存使用之间的关系。

maxsize参数最好设置为2的幂次方,这样可以在内部哈希表扩展时更加高效。例如,可以设置为1024、2048、4096等。


1-3、缓存操作:缓存对象支持类似字典的操作

例如:添加、获取、删除和更新缓存项

# 类似于字典操作
# 添加缓存项
lru_cache["key"] = "value"
# 获取缓存项
value = lru_cache.get("key", "default_value")
# 删除缓存项
if "key" in lru_cache:
    del lru_cache["key"]
# 更新缓存项
lru_cache["key"] = "new_value"


1-4、设置数据生存时间(TTL)


cachetools : 还支持为缓存项设置生存时间(TTL)。当缓存项的生存时间到期后,该项将被自动移除。


import cachetools
import time
# 创建一个带 TTL 的缓存对象
ttl_cache = cachetools.TTLCache(maxsize=100, ttl=60)
# 添加缓存项
ttl_cache["key"] = "value"
# 等待一段时间,让缓存项过期
time.sleep(61)
# 此时缓存项已过期,尝试获取时将返回默认值
value = ttl_cache.get("key", "default_value")


1-5、自定义缓存策略


cachetools: 允许自定义缓存策略。要实现一个自定义的缓存策略,需要继承 cachetools.Cache 类,并实现相应的方法。例如,实现一个简单的大小有限制的缓存:

import cachetools
class SizeLimitedCache(cachetools.Cache):
    def __init__(self, maxsize):
        super().__init__(maxsize=maxsize)
    def __getitem__(self, key, cache_getitem=dict.__getitem__):
        return cache_getitem(self, key)
    def __setitem__(self, key, value, cache_setitem=dict.__setitem__):
        if len(self) >= self.maxsize:
            self.popitem(last=False)  # 删除第一个缓存项
        cache_setitem(self, key, value)
# 使用自定义缓存策略
custom_cache = SizeLimitedCache(maxsize=100)


1-6、缓存装饰器

cachetools: 还提供了一些缓存装饰器,可以方便地将缓存应用于函数或方法。

import cachetools
# 使用 LRU 缓存装饰函数
@cachetools.func.ttl_cache(maxsize=100, ttl=60)
def get_data_from_api(api_url, params):
    response = requests.get(api_url, params=params)
    response.raise_for_status()
    data = response.json()
    return data
# 使用缓存的函数
data = get_data_from_api("https://api.example.com/data", {"param1": "value1", "param2": "value2"})


1-7、缓存清理

cachetools: 提供了一些方法,可以手动清理缓存

import cachetools
# 创建 LRU 缓存
lru_cache = cachetools.LRUCache(maxsize=100)
# 手动清空缓存
lru_cache.clear()
# 移除所有过期缓存项
lru_cache.expire()
# 移除最近最少使用的缓存项
lru_cache.popitem(last=False)


二、cachetools 使用示例


在这个示例中,我们使用 cachetools.LRUCache 创建一个 LRU 缓存。当我们调用 get_data_from_api() 函数时,会先检查缓存中是否有数据。如果缓存中有数据,就直接返回缓存的数据,避免了重复请求接口,提高了程序性能。

import requests
import cachetools
# 创建一个 LRU 缓存,最大容量为 100
cache = cachetools.LRUCache(maxsize=100)
def get_data_from_api(url):
    if url in cache:
        return cache[url]  # 如果数据已经在缓存中,直接返回缓存的数据
    response = requests.get(url)
    response.raise_for_status()
    data = response.json()
    cache[url] = data  # 将数据存储在缓存中
    return data
# 使用缓存的函数
data = get_data_from_api("https://api.example.com/data")


三、错误汇总

3-1、TypeError: unhashable type: ‘dict’


错误来源:我想要直接将一个字典,作为cachetools缓存的键(key),这样是会报错的。


这个错误是因为字典(dict)类型在Python中是不可哈希(unhashable)的,因此不能直接将字典作为cachetools缓存的键(key)。要解决这个问题,可以将字典转换为一个可哈希的类型,比如字符串(str)或元组(tuple)。


以下是一个示例,将字典转换为字符串作为键:

import requests
import cachetools
import json
cache = cachetools.LRUCache(maxsize=100)
def get_data_from_api(api_url, params):
    # 将字典转换为字符串,并确保key的顺序一致,避免相同内容的字典生成不同的字符串
    cache_key = json.dumps(params, sort_keys=True)
    if cache_key in cache:
        return cache[cache_key]
    response = requests.get(api_url, params=params)
    response.raise_for_status()
    data = response.json()
    cache[cache_key] = data
    return data
# 使用缓存的函数
params = {"param1": "value1", "param2": "value2"}
data = get_data_from_api("https://api.example.com/data", params)


在这个示例中,我们将params字典转换为一个字符串,然后将字符串作为缓存的键。当调用接口获取数据时,Python会检查缓存中是否有数据。如果缓存中有数据,就直接返回缓存的数据,避免了重复请求接口,提高了程序性能。


总结


emmm,五一前忘记倒掉壶里的茶水了,都长毛了!!

相关文章
|
4天前
|
机器学习/深度学习 数据采集 算法
Python实现ISSA融合反向学习与Levy飞行策略的改进麻雀优化算法优化支持向量机回归模型(SVR算法)项目实战
Python实现ISSA融合反向学习与Levy飞行策略的改进麻雀优化算法优化支持向量机回归模型(SVR算法)项目实战
|
3天前
|
存储 算法 搜索推荐
算法进阶之路:Python 归并排序深度剖析,让数据排序变得艺术起来!
【7月更文挑战第12天】归并排序是高效稳定的排序算法,采用分治策略。Python 实现包括递归地分割数组及合并已排序部分。示例代码展示了如何将 `[12, 11, 13, 5, 6]` 分割并归并成有序数组 `[5, 6, 11, 12, 13]`。虽然 $O(n log n)$ 时间复杂度优秀,但需额外空间,适合大规模数据排序。对于小规模数据,可考虑其他算法。**
15 4
|
3天前
|
网络协议 Python
Scapy一个强大的 Python 程序(一)
Scapy是Python的网络数据包操作工具,用于创建、分析和发送网络包。启动Scapy需以管理员权限运行`sudo scapy`。在交互式环境中,可构建自定义数据包,如设置IP包的`ttl`、`src`和`dst`。通过`/`叠加协议层,如IP和TCP。发送数据包示例:构造向`www.slashdot.org`的HTTP GET请求。Scapy还能用于嗅探、过滤和修改数据包,功能强大。
|
4天前
|
机器学习/深度学习 数据采集 算法
Python实现WOA智能鲸鱼优化算法优化支持向量机分类模型(SVC算法)项目实战
Python实现WOA智能鲸鱼优化算法优化支持向量机分类模型(SVC算法)项目实战
|
2天前
|
网络协议 安全 Python
Scapy一个强大的 Python 程序(二)
Scapy是Python的网络安全工具,可用于创建和修改网络包
|
2天前
|
存储 算法 Python
“解锁Python高级数据结构新姿势:图的表示与遍历,让你的算法思维跃升新高度
【7月更文挑战第13天】Python中的图数据结构用于表示复杂关系,通过节点和边连接。常见的表示方法是邻接矩阵(适合稠密图)和邻接表(适合稀疏图)。图遍历包括DFS(深度优先搜索)和BFS(广度优先搜索):DFS深入探索分支,BFS逐层访问邻居。掌握这些技巧对优化算法和解决实际问题至关重要。**
9 1
|
4天前
|
机器学习/深度学习 数据采集 算法
Python实现ISSA融合反向学习与Levy飞行策略的改进麻雀优化算法优化支持向量机分类模型(SVC算法)项目实战
Python实现ISSA融合反向学习与Levy飞行策略的改进麻雀优化算法优化支持向量机分类模型(SVC算法)项目实战
|
4天前
|
机器学习/深度学习 数据采集 算法
Python实现GBDT(梯度提升树)分类模型(GradientBoostingClassifier算法)并应用网格搜索算法寻找最优参数项目实战
Python实现GBDT(梯度提升树)分类模型(GradientBoostingClassifier算法)并应用网格搜索算法寻找最优参数项目实战
|
4天前
|
机器学习/深度学习 数据采集 算法
Python实现WOA智能鲸鱼优化算法优化支持向量机回归模型(LinearSVR算法)项目实战
Python实现WOA智能鲸鱼优化算法优化支持向量机回归模型(LinearSVR算法)项目实战
|
4天前
|
机器学习/深度学习 数据采集 算法
Python实现SSA智能麻雀搜索算法优化支持向量机回归模型(SVR算法)项目实战
Python实现SSA智能麻雀搜索算法优化支持向量机回归模型(SVR算法)项目实战