Python cache 內存泄漏問題
@functools.cache 函數裝飾器在一些特殊情況的時候會影響變量引用計數器的計數,從而導致內存泄漏。比如:@functools.cache和@@functools.property一起使用的時候,或者更復雜的嵌套引用
1 from functools import wraps 2 3 4 class CacheManager: 5 def __init__(self): 6 self._cache = {} 7 8 def get_cache_obj(self, key): 9 """獲取緩存對象""" 10 return self._cache.get(key) 11 12 def add_cache_obj(self, key, obj): 13 """添加緩存對象""" 14 self._cache[key] = obj 15 return obj 16 17 def __del__(self): 18 """清除所有緩存對象""" 19 # print(f"CacheManager del") 20 for k, v in self._cache.items(): 21 # print(f"CacheManager del:{k=}") 22 del v 23 self._cache.clear() 24 del self._cache 25 26 @classmethod 27 def cache_result(cls, func): 28 """ 29 裝飾器:緩存結果,支持參數作為緩存的唯一鍵。 30 """ 31 32 @wraps(func) 33 def wrapper(instance, *args, **kwargs): 34 # 根據函數名和參數構建唯一緩存鍵 35 key = f"{func.__name__}:{args}:{kwargs}" 36 37 # 檢查是否已緩存 38 cache_obj = instance.cache_manager.get_cache_obj(key) 39 if cache_obj is not None: 40 return cache_obj 41 42 # 緩存中沒有對象,執行函數并緩存結果 43 result = func(instance, *args, **kwargs) 44 instance.cache_manager.add_cache_obj(key, result) 45 return result 46 47 return wrapper
測試demo
1 from base.utils.tools import CacheManager 2 3 4 class MyClass: 5 def __init__(self): 6 self.cache_manager = CacheManager() 7 8 def __del__(self): 9 print("MyClass.__del__") 10 11 @property 12 @CacheManager.cache_result 13 def oms_user(self): 14 # 該代碼只在緩存不存在時執行 15 return [1, 2, 3] 16 17 18 def test_cache(): 19 m = MyClass() 20 print(id(m.oms_user)) 21 print(id(m.oms_user))

浙公網安備 33010602011771號