| import os |
| import json |
| import hashlib |
| import pickle |
| from typing import Any, Optional, Dict |
| from pathlib import Path |
| from config import Config |
|
|
| class CacheManager: |
| """缓存管理器""" |
| |
| def __init__(self, cache_dir: str = None): |
| self.cache_dir = cache_dir or Config.CACHE_DIR |
| Path(self.cache_dir).mkdir(parents=True, exist_ok=True) |
| |
| def _get_cache_key(self, *args, **kwargs) -> str: |
| """生成缓存键""" |
| content = str(args) + str(sorted(kwargs.items())) |
| return hashlib.md5(content.encode()).hexdigest() |
| |
| def _get_cache_path(self, key: str) -> str: |
| """获取缓存文件路径""" |
| return os.path.join(self.cache_dir, f"{key}.pkl") |
| |
| def get(self, key: str) -> Optional[Any]: |
| """获取缓存""" |
| if not Config.ENABLE_CACHE: |
| return None |
| |
| cache_file = self._get_cache_path(key) |
| if os.path.exists(cache_file): |
| try: |
| with open(cache_file, 'rb') as f: |
| return pickle.load(f) |
| except Exception as e: |
| print(f"读取缓存失败 ({key}): {e}") |
| return None |
| return None |
| |
| def set(self, key: str, value: Any) -> bool: |
| """设置缓存""" |
| if not Config.ENABLE_CACHE: |
| return False |
| |
| cache_file = self._get_cache_path(key) |
| try: |
| with open(cache_file, 'wb') as f: |
| pickle.dump(value, f) |
| return True |
| except Exception as e: |
| print(f"缓存保存失败 ({key}): {e}") |
| return False |
| |
| def exists(self, key: str) -> bool: |
| """检查缓存是否存在""" |
| if not Config.ENABLE_CACHE: |
| return False |
| return os.path.exists(self._get_cache_path(key)) |
| |
| def delete(self, key: str) -> bool: |
| """删除指定缓存""" |
| cache_file = self._get_cache_path(key) |
| if os.path.exists(cache_file): |
| try: |
| os.remove(cache_file) |
| return True |
| except Exception as e: |
| print(f"删除缓存失败 ({key}): {e}") |
| return False |
| return False |
| |
| def clear(self, pattern: str = None): |
| """清除缓存""" |
| if not os.path.exists(self.cache_dir): |
| return |
| |
| count = 0 |
| for file in os.listdir(self.cache_dir): |
| if file.endswith('.pkl'): |
| if pattern is None or pattern in file: |
| try: |
| os.remove(os.path.join(self.cache_dir, file)) |
| count += 1 |
| except Exception as e: |
| print(f"删除缓存文件失败 ({file}): {e}") |
| |
| print(f"已清除 {count} 个缓存文件") |
| |
| def get_cache_size(self) -> int: |
| """获取缓存总大小(字节)""" |
| if not os.path.exists(self.cache_dir): |
| return 0 |
| |
| total_size = 0 |
| for file in os.listdir(self.cache_dir): |
| if file.endswith('.pkl'): |
| file_path = os.path.join(self.cache_dir, file) |
| total_size += os.path.getsize(file_path) |
| |
| return total_size |
| |
| def get_cache_info(self) -> dict: |
| """获取缓存信息""" |
| if not os.path.exists(self.cache_dir): |
| return { |
| 'count': 0, |
| 'size': 0, |
| 'size_mb': 0 |
| } |
| |
| count = 0 |
| total_size = 0 |
| |
| for file in os.listdir(self.cache_dir): |
| if file.endswith('.pkl'): |
| count += 1 |
| file_path = os.path.join(self.cache_dir, file) |
| total_size += os.path.getsize(file_path) |
| |
| return { |
| 'count': count, |
| 'size': total_size, |
| 'size_mb': round(total_size / (1024 * 1024), 2) |
| } |
| |
| def save_json(self, key: str, data: dict) -> bool: |
| """保存为JSON格式(用于可读性)""" |
| cache_file = os.path.join(self.cache_dir, f"{key}.json") |
| try: |
| with open(cache_file, 'w', encoding='utf-8') as f: |
| json.dump(data, f, ensure_ascii=False, indent=2) |
| return True |
| except Exception as e: |
| print(f"保存JSON缓存失败 ({key}): {e}") |
| return False |
| |
| def load_json(self, key: str) -> Optional[dict]: |
| """加载JSON格式缓存""" |
| cache_file = os.path.join(self.cache_dir, f"{key}.json") |
| if os.path.exists(cache_file): |
| try: |
| with open(cache_file, 'r', encoding='utf-8') as f: |
| return json.load(f) |
| except Exception as e: |
| print(f"读取JSON缓存失败 ({key}): {e}") |
| return None |
| return None |