Python脚本如何持久化保存缓存数据

wen python案例 31

本文目录导读:

Python脚本如何持久化保存缓存数据

  1. 使用 pickle 序列化(最简单)
  2. 使用 JSON 格式(可读性好)
  3. 使用 SQLite 数据库(适合大量数据)
  4. 使用 Redis(生产环境推荐)
  5. 使用 shelve(内置库,类似字典的持久化)
  6. 使用 diskcache 库(功能最完整)
  7. 选择建议
  8. 最佳实践建议

在Python中持久化保存缓存数据,主要有以下几种常见方法和实现方案:

使用 pickle 序列化(最简单)

import pickle
import os
class SimpleCache:
    def __init__(self, cache_file='cache.pkl'):
        self.cache_file = cache_file
        self.data = self.load_cache()
    def load_cache(self):
        if os.path.exists(self.cache_file):
            with open(self.cache_file, 'rb') as f:
                return pickle.load(f)
        return {}
    def save_cache(self):
        with open(self.cache_file, 'wb') as f:
            pickle.dump(self.data, f)
    def set(self, key, value):
        self.data[key] = value
        self.save_cache()
    def get(self, key):
        return self.data.get(key)
# 使用示例
cache = SimpleCache()
cache.set('user_123', {'name': 'Alice', 'age': 30})
print(cache.get('user_123'))

使用 JSON 格式(可读性好)

import json
import os
class JSONCache:
    def __init__(self, cache_file='cache.json'):
        self.cache_file = cache_file
        self.data = self.load_cache()
    def load_cache(self):
        if os.path.exists(self.cache_file):
            with open(self.cache_file, 'r', encoding='utf-8') as f:
                return json.load(f)
        return {}
    def save_cache(self):
        with open(self.cache_file, 'w', encoding='utf-8') as f:
            json.dump(self.data, f, ensure_ascii=False, indent=2)
    def set(self, key, value):
        self.data[key] = value
        self.save_cache()
    def get(self, key):
        return self.data.get(key)
# 使用示例
cache = JSONCache()
cache.set('search_history', ['python', 'json', 'caching'])
print(cache.get('search_history'))

使用 SQLite 数据库(适合大量数据)

import sqlite3
import json
from datetime import datetime, timedelta
class SQLiteCache:
    def __init__(self, db_file='cache.db', expire_seconds=3600):
        self.db_file = db_file
        self.expire_seconds = expire_seconds
        self.init_db()
    def init_db(self):
        with sqlite3.connect(self.db_file) as conn:
            conn.execute('''
                CREATE TABLE IF NOT EXISTS cache (
                    key TEXT PRIMARY KEY,
                    value TEXT,
                    expire_time TIMESTAMP
                )
            ''')
    def set(self, key, value):
        expire_time = datetime.now() + timedelta(seconds=self.expire_seconds)
        with sqlite3.connect(self.db_file) as conn:
            conn.execute(
                'INSERT OR REPLACE INTO cache (key, value, expire_time) VALUES (?, ?, ?)',
                (key, json.dumps(value), expire_time)
            )
    def get(self, key):
        with sqlite3.connect(self.db_file) as conn:
            cursor = conn.execute(
                'SELECT value, expire_time FROM cache WHERE key = ?',
                (key,)
            )
            row = cursor.fetchone()
            if row:
                value, expire_time = row
                if datetime.now() < datetime.strptime(expire_time, '%Y-%m-%d %H:%M:%S.%f'):
                    return json.loads(value)
                else:
                    self.delete(key)  # 自动清理过期数据
        return None
    def delete(self, key):
        with sqlite3.connect(self.db_file) as conn:
            conn.execute('DELETE FROM cache WHERE key = ?', (key,))
# 使用示例
cache = SQLiteCache('my_cache.db', expire_seconds=3600)
cache.set('api_response', {'status': 'ok', 'data': [1, 2, 3]})
result = cache.get('api_response')
print(result)

使用 Redis(生产环境推荐)

import redis
import json
class RedisCache:
    def __init__(self, host='localhost', port=6379, db=0, expire_seconds=3600):
        self.client = redis.Redis(host=host, port=port, db=db)
        self.expire_seconds = expire_seconds
    def set(self, key, value):
        self.client.setex(
            key,
            self.expire_seconds,
            json.dumps(value)
        )
    def get(self, key):
        value = self.client.get(key)
        if value:
            return json.loads(value)
        return None
    def delete(self, key):
        self.client.delete(key)
    def clear_all(self):
        self.client.flushdb()
# 需要安装 redis: pip install redis
# 使用示例
cache = RedisCache()
cache.set('session:user123', {'login_time': '2024-01-01', 'permissions': ['read', 'write']})
print(cache.get('session:user123'))

使用 shelve(内置库,类似字典的持久化)

import shelve
class ShelfCache:
    def __init__(self, filename='cache.shelve'):
        self.filename = filename
    def set(self, key, value):
        with shelve.open(self.filename) as shelf:
            shelf[key] = value
    def get(self, key):
        with shelve.open(self.filename) as shelf:
            return shelf.get(key)
    def delete(self, key):
        with shelve.open(self.filename) as shelf:
            if key in shelf:
                del shelf[key]
# 使用示例
cache = ShelfCache()
cache.set('config', {'theme': 'dark', 'language': 'zh_CN'})
print(cache.get('config'))

使用 diskcache 库(功能最完整)

from diskcache import Cache
class DiskCacheWrapper:
    def __init__(self, directory='./cache', size_limit=100*(1024**2)):  # 100MB
        self.cache = Cache(directory, size_limit=size_limit)
    def set(self, key, value, expire=None):
        self.cache.set(key, value, expire=expire)
    def get(self, key, default=None):
        return self.cache.get(key, default)
    def delete(self, key):
        del self.cache[key]
# 需要安装: pip install diskcache
# 使用示例
cache = DiskCacheWrapper()
cache.set('computed_result', {'value': 42, 'timestamp': '2024-01-01'}, expire=3600)
print(cache.get('computed_result'))

选择建议

方法 适用场景 优点 缺点
pickle 小数据量、单机 简单、支持任何对象 不安全、不可读
JSON 需要人工查看数据 可读性好、跨语言 只支持基本类型
SQLite 中等数据量、结构化数据 支持查询、过期 需要SQL知识
Redis 高并发、分布式系统 高性能、内存级 需要额外服务
shelve 简单键值存储 内置库、API简单 性能一般
diskcache 需要高级功能 功能完整、性能好 第三方依赖

最佳实践建议

import hashlib
from functools import wraps
def cached(cache_instance, expire=3600):
    """缓存装饰器"""
    def decorator(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            # 生成缓存键
            key = f"{func.__name__}:{hashlib.md5(str(args).encode()).hexdigest()}"
            # 尝试获取缓存
            result = cache_instance.get(key)
            if result is not None:
                print(f"Cache hit for {key}")
                return result
            # 执行函数
            result = func(*args, **kwargs)
            # 保存缓存
            cache_instance.set(key, result)
            print(f"Cache miss for {key}")
            return result
        return wrapper
    return decorator
# 使用示例
cache = JSONCache('app_cache.json')
@cached(cache, expire=300)  # 5分钟过期
def expensive_function(user_id):
    # 模拟耗时操作
    import time
    time.sleep(2)
    return {'user_id': user_id, 'data': 'some expensive data'}
# 第一次调用会执行函数
result1 = expensive_function(123)
# 第二次调用会从缓存获取
result2 = expensive_function(123)

根据你的具体需求(数据量、并发要求、是否需要过期时间等)选择合适的方案,对于大多数中小型项目,使用 JSON + 文件存储 或 SQLite 就足够了。

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