Python 3.11中lru_cache不生效:多次运行后cache_info无变化
问题:lru_cache装饰器缓存信息无变化的原因
首次测试lru_cache装饰器,编写了一段网络请求代码,代码可正常运行,但多次执行后cache_info()的输出始终未发生变化。
代码示例
import requests from functools import lru_cache url = 'http://www.python.org/dev/peps/pep-' my_list = [290, 308, 320, 8, 218, 320, 279, 289, 320] @lru_cache(maxsize=20, typed=False) def fetch_data(): for item in my_list: data = requests.get(url+str(item)) print(len(data.text)) if __name__ == "__main__": fetch_data() print(fetch_data.cache_info())
执行结果
53159 41324 21598 118304 20618 21598 20153 30451 21598 CacheInfo(hits=0, misses=1, maxsize=20, currsize=1) ➜ ~ /usr/local/bin/python3 pythonProject/main_6.py 53159 41324 21598 118304 20618 21598 20153 30451 21598 CacheInfo(hits=0, misses=1, maxsize=20, currsize=1)
原因分析
1. 进程级缓存的生命周期问题
你每次都是重新运行整个Python脚本,而lru_cache的缓存是进程级的——脚本运行结束后,进程销毁,缓存也会被完全清空。所以每次运行脚本都是全新的执行环境,fetch_data()都是第一次被调用,自然每次的cache_info输出都是hits=0, misses=1。
2. 缓存粒度完全错误
你的fetch_data函数没有参数,lru_cache会以函数的调用签名(此处为无参)作为缓存key,缓存的是整个函数的执行结果(你的函数没有返回值,默认返回None)。哪怕在同一个脚本里多次调用fetch_data(),第二次调用时会直接命中缓存,不会执行内部的请求循环,但你当前写法里每次只调用一次,也体现不出缓存效果。
而你真正需要缓存的是单个PEP链接的请求结果,但现在把包含循环的整个函数加了缓存,完全没达到预期的缓存目标。
修正方案
把单个请求的逻辑抽成带参数的独立函数,用PEP编号作为缓存key,这样重复的请求会被缓存:
import requests from functools import lru_cache url = 'http://www.python.org/dev/peps/pep-' my_list = [290, 308, 320, 8, 218, 320, 279, 289, 320] @lru_cache(maxsize=20, typed=False) def fetch_pep(pep_num): data = requests.get(url + str(pep_num)) return len(data.text) def fetch_data(): for item in my_list: length = fetch_pep(item) print(length) if __name__ == "__main__": fetch_data() print(fetch_pep.cache_info())
运行这段代码,你会看到cache_info里的hits=2(因为320出现了3次,后两次命中缓存)、misses=6(6个唯一的PEP编号),符合预期。如果在同一个脚本里多次调用fetch_data(),后续调用的hits数值还会继续增加。
内容的提问来源于stack exchange,提问作者marqeu
相关产品推荐
相关产品推荐

