Python脚本如何修复损坏缓存数据

wen python案例 33

本文目录导读:

Python脚本如何修复损坏缓存数据

  1. 通用修复流程
  2. 修复JSON格式的缓存文件
  3. 修复SQLite缓存数据库
  4. 修复文件系统缓存(目录结构异常)
  5. 综合示例:检测并修复多种缓存类型
  6. 重要注意事项

修复损坏的缓存数据通常需要根据缓存的具体类型(如文件缓存、数据库缓存或内存缓存)来采取不同的策略,以下是一个通用的 Python 脚本框架及具体场景的示例,帮助你修复常见的缓存损坏问题。


通用修复流程

import os
import json
import shutil
import sqlite3
from pathlib import Path
class CacheRepair:
    def __init__(self, cache_path):
        self.cache_path = Path(cache_path)
    def backup(self):
        """修复前先备份"""
        backup_path = self.cache_path.with_suffix('.bak')
        if self.cache_path.exists():
            shutil.copy2(self.cache_path, backup_path)
            print(f"备份已创建: {backup_path}")
        return backup_path
    def restore(self, backup_path=None):
        """恢复备份"""
        if backup_path and backup_path.exists():
            shutil.copy2(backup_path, self.cache_path)
            print(f"已从备份恢复: {backup_path}")
        else:
            print("没有可用的备份")
    def clear(self):
        """清空缓存"""
        if self.cache_path.is_dir():
            shutil.rmtree(self.cache_path)
            self.cache_path.mkdir(parents=True)
        elif self.cache_path.is_file():
            self.cache_path.write_text('')
        print("缓存已清空")

修复JSON格式的缓存文件

场景:缓存存储为 JSON 文件,但内容格式错误或部分损坏。

import json
from pathlib import Path
def repair_json_cache(cache_file: Path, schema: dict = None):
    """
    修复损坏的JSON缓存
    :param cache_file: 缓存文件路径
    :param schema: 可选,期望的JSON结构模板,用于重建缺失字段
    """
    try:
        with open(cache_file, 'r', encoding='utf-8') as f:
            data = json.load(f)
    except (json.JSONDecodeError, FileNotFoundError) as e:
        print(f"缓存文件损坏或不存在: {e}")
        # 尝试恢复:如果文件有部分内容,尝试提取有效JSON
        data = _extract_valid_json(cache_file)
        if data is None:
            print("无法修复,将重置为空缓存")
            data = {} if schema is None else schema.copy()
    # 验证字段完整性(如果有schema)
    if schema and isinstance(data, dict):
        for key, default_value in schema.items():
            if key not in data:
                print(f"缺少字段 {key},使用默认值 {default_value}")
                data[key] = default_value
    with open(cache_file, 'w', encoding='utf-8') as f:
        json.dump(data, f, indent=2)
    return data
def _extract_valid_json(file_path: Path):
    """尝试从损坏文件中提取有效的JSON片段"""
    try:
        content = file_path.read_text(encoding='utf-8')
        # 找到第一个 '{' 和最后一个 '}' 之间的内容
        start = content.find('{')
        end = content.rfind('}')
        if start != -1 and end != -1 and start < end:
            candidate = content[start:end+1]
            return json.loads(candidate)
    except Exception:
        pass
    return None

修复SQLite缓存数据库

场景:缓存存储在 SQLite 文件中,存在数据损坏或表结构异常。

import sqlite3
from pathlib import Path
def repair_sqlite_cache(db_path: Path, expected_tables: list):
    """
    修复SQLite缓存数据库
    :param db_path: 数据库文件路径
    :param expected_tables: 期望存在的表名列表
    """
    conn = sqlite3.connect(str(db_path))
    cursor = conn.cursor()
    # 1. 检查数据库完整性
    cursor.execute("PRAGMA integrity_check")
    result = cursor.fetchone()[0]
    if result != "ok":
        print(f"数据库完整性检查失败: {result}")
        # 尝试先执行备份、恢复或导出导入
        print("尝试使用 VACUUM 和 REINDEX 修复...")
        cursor.execute("PRAGMA quick_check")
        cursor.execute("VACUUM")
        cursor.execute("REINDEX")
        conn.commit()
        # 再次检查
        cursor.execute("PRAGMA integrity_check")
        if cursor.fetchone()[0] != "ok":
            print("自动修复失败,需要从备份恢复或重建")
            conn.close()
            return False
    # 2. 检查表是否存在
    cursor.execute("SELECT name FROM sqlite_master WHERE type='table'")
    existing_tables = {row[0] for row in cursor.fetchall()}
    for table in expected_tables:
        if table not in existing_tables:
            print(f"缺少表 {table},尝试创建...")
            if table == "cache_entries":
                cursor.execute('''
                    CREATE TABLE IF NOT EXISTS cache_entries (
                        key TEXT PRIMARY KEY,
                        value BLOB,
                        expire_time REAL
                    )
                ''')
            elif table == "metadata":
                cursor.execute('''
                    CREATE TABLE IF NOT EXISTS metadata (
                        name TEXT PRIMARY KEY,
                        value TEXT
                    )
                ''')
            conn.commit()
    conn.close()
    return True

修复文件系统缓存(目录结构异常)

场景:缓存存储在大量小文件中,出现权限、文件名编码或硬链接问题。

import os
import stat
from pathlib import Path
def repair_file_cache(cache_dir: Path):
    """
    修复文件系统缓存
    - 统一权限
    - 清理非法文件名
    - 删除空目录
    """
    if not cache_dir.exists():
        print("缓存目录不存在,创建中...")
        cache_dir.mkdir(parents=True, exist_ok=True)
        return
    fixed_count = 0
    for root, dirs, files in os.walk(cache_dir):
        for name in files + dirs:
            path = Path(root) / name
            # 修复文件名编码问题(例如将非法字符替换)
            try:
                # 尝试用UTF-8重新编码解码文件名
                new_name = name.encode('utf-8', errors='replace').decode('utf-8')
                if new_name != name:
                    new_path = path.parent / new_name
                    path.rename(new_path)
                    print(f"修复文件名: {path} -> {new_path}")
                    fixed_count += 1
                    path = new_path
            except Exception:
                pass
            # 修复权限(确保目录可读,文件可读写)
            try:
                if path.is_dir():
                    path.chmod(stat.S_IRWXU | stat.S_IRWXG | stat.S_IROTH | stat.S_IXOTH)
                else:
                    path.chmod(stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | stat.S_IWGRP)
            except Exception as e:
                print(f"权限修复失败: {path} - {e}")
    # 删除空目录
    for root, dirs, files in os.walk(cache_dir, topdown=False):
        for dir_name in dirs:
            dir_path = Path(root) / dir_name
            try:
                if not any(dir_path.iterdir()):
                    dir_path.rmdir()
                    print(f"删除空目录: {dir_path}")
                    fixed_count += 1
            except Exception:
                pass
    print(f"文件缓存修复完成,共处理 {fixed_count} 个问题")

综合示例:检测并修复多种缓存类型

def repair_all_caches(config: dict):
    """
    根据配置文件修复多种缓存
    config 示例:
    {
        "json_cache": {"path": "/tmp/cache/data.json", "schema": {"last_update": None}},
        "sqlite_cache": {"path": "/tmp/cache/db.sqlite", "tables": ["cache_entries", "metadata"]},
        "file_cache": {"path": "/tmp/cache/files"}
    }
    """
    for cache_type, params in config.items():
        print(f"正在修复 {cache_type}...")
        try:
            if cache_type == "json_cache":
                repair_json_cache(Path(params["path"]), params.get("schema"))
            elif cache_type == "sqlite_cache":
                repair_sqlite_cache(Path(params["path"]), params["tables"])
            elif cache_type == "file_cache":
                repair_file_cache(Path(params["path"]))
            else:
                print(f"未知的缓存类型: {cache_type}")
        except Exception as e:
            print(f"修复 {cache_type} 失败: {e}")
# 使用示例
config = {
    "json_cache": {
        "path": "./cache/app_config.json",
        "schema": {"version": 1, "settings": {}}
    },
    "sqlite_cache": {
        "path": "./cache/response_cache.db",
        "tables": ["cache_entries"]
    }
}
repair_all_caches(config)

重要注意事项

  1. 备份优先:任何修复操作前都应先备份原始缓存,防止修复失败导致数据完全丢失。
  2. 日志记录:记录所有修复操作,便于后续排查问题。
  3. 异常处理:修复脚本本身可能因权限、磁盘空间不足等原因失败,需做好异常捕获。
  4. 原子性:对于关键缓存,建议将修复操作放在事务中执行(如 SQLite 的 BEGIN / COMMIT)。
  5. 定期维护:将缓存修复脚本集成到定期维护任务中(如 cron job),预防潜在问题。

根据你的具体缓存类型(如 Redis、Memcached、自定义 pickle 文件等),需要调整对应的修复逻辑,如果缓存损坏的原因是版本不兼容,还需要考虑数据迁移或重建索引的策略。

抱歉,评论功能暂时关闭!