|
|
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 |