You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python脚本执行间持久化数据:有无更简便的缓存序列方法?

Python 简便缓存可更新数值序列的方案

问题背景

我想了解Python是否具备简便的方法来缓存可更新的数值序列,使得脚本每次运行时都能向序列中添加新值,且下次运行时能保留这些数据。例如,我有一个由datetime和float类型组成的元组列表,其中datetime代表风速仪的记录时间,float代表记录的风速。

我最初用pickle实现,代码如下:

import os
import pickle
import datetime

db_path = "speeds.p"

# get all our previous speeds
speeds = []
if os.path.exists(db_path):
    with open(db_path, "rb") as f:
        speeds = pickle.load(f)


def data_from_endpoint():
    data = (
        (datetime.datetime(2022, 10, 22, 21, 15), 13),
        (datetime.datetime(2022, 10, 22, 21, 30), 24),
        (datetime.datetime(2022, 10, 22, 21, 45), 37)
    )

    for i in data:
        yield i


try:
    # add new speeds
    for t, v in data_from_endpoint():
        if len(speeds) == 0 or t > speeds[-1][0]:
            print(f"Adding {t}, {v}")
            speeds.append((t, v))
finally:
    # save all speeds
    with open(db_path, "wb") as f:
        pickle.dump(speeds, f)

print(f"Number of values: {len(speeds)}")

后来改用sqlite,但两种方案代码量都不小,想找更简单的实现方式。

简便实现方案

1. 使用标准库 shelve(推荐,无需额外安装)

shelve是Python内置的键值对存储工具,基于pickle实现,省去了手动处理文件存在性判断、IO异常的代码,用法更简洁。

示例代码:

import shelve
import datetime

def data_from_endpoint():
    data = (
        (datetime.datetime(2022, 10, 22, 21, 15), 13),
        (datetime.datetime(2022, 10, 22, 21, 30), 24),
        (datetime.datetime(2022, 10, 22, 21, 45), 37)
    )
    for i in data:
        yield i

# 打开shelve数据库,自动处理文件创建/读取
with shelve.open('speeds_db') as db:
    # 获取已有数据,默认返回空列表
    speeds = db.get('speeds', [])
    # 添加新数据(保留时间戳递增逻辑)
    for t, v in data_from_endpoint():
        if not speeds or t > speeds[-1][0]:
            print(f"Adding {t}, {v}")
            speeds.append((t, v))
    # 保存更新后的数据
    db['speeds'] = speeds
    print(f"Number of values: {len(speeds)}")

核心优势:

  • 无需额外安装依赖,开箱即用
  • 自动处理文件IO流程,代码量比手动pickle减少近一半
  • 支持存储大部分Python原生对象(包括datetime、元组等)

2. 使用 pandas 快速序列化(适合数据分析场景)

如果你的项目已经依赖pandas,用它的序列化工具可以进一步简化代码,同时还能直接利用pandas的数据处理能力。

示例代码:

import pandas as pd
import datetime

def data_from_endpoint():
    data = (
        (datetime.datetime(2022, 10, 22, 21, 15), 13),
        (datetime.datetime(2022, 10, 22, 21, 30), 24),
        (datetime.datetime(2022, 10, 22, 21, 45), 37)
    )
    return pd.DataFrame(data, columns=['timestamp', 'speed'])

# 读取已有数据,不存在则创建空DataFrame
try:
    df = pd.read_pickle('speeds_df.pkl')
except FileNotFoundError:
    df = pd.DataFrame(columns=['timestamp', 'speed'])

new_df = data_from_endpoint()
# 筛选未存在的新时间戳
new_entries = new_df[new_df['timestamp'] > df['timestamp'].max()] if not df.empty else new_df
# 合并数据并保存
df = pd.concat([df, new_entries], ignore_index=True)
df.to_pickle('speeds_df.pkl')

print(f"Number of values: {len(df)}")

核心优势:

  • 适合后续需要做风速统计、可视化的场景
  • 内置数据去重、筛选逻辑,无需手动写判断
  • 支持更高效的序列化格式(如feather、parquet)

3. 使用 diskcache 第三方库(功能丰富的缓存工具)

如果需要更灵活的缓存控制(比如设置过期时间、缓存大小限制),可以用diskcache,安装后用法同样简洁。

先安装依赖:

pip install diskcache

示例代码:

from diskcache import Cache
import datetime

def data_from_endpoint():
    data = (
        (datetime.datetime(2022, 10, 22, 21, 15), 13),
        (datetime.datetime(2022, 10, 22, 21, 30), 24),
        (datetime.datetime(2022, 10, 22, 21, 45), 37)
    )
    for i in data:
        yield i

# 创建缓存实例
cache = Cache('speeds_cache')
# 获取已有数据,默认空列表
speeds = cache.get('speeds', [])
# 添加新数据
for t, v in data_from_endpoint():
    if not speeds or t > speeds[-1][0]:
        print(f"Adding {t}, {v}")
        speeds.append((t, v))
# 保存更新
cache.set('speeds', speeds)
print(f"Number of values: {len(speeds)}")
# 关闭缓存连接
cache.close()

核心优势:

  • 支持并发访问,适合多进程/线程场景
  • 可设置缓存过期时间、自动清理策略
  • 性能优于shelve,适合大规模数据存储

内容的提问来源于stack exchange,提问作者Baz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 00:30:54