Skip to main content

nltcache

一个简洁的 Python 函数缓存装饰器库,提供多种缓存策略,涵盖内存缓存、磁盘缓存和 Pickle 文件缓存。

安装

pip install nltcache

要求 Python >= 3.10。

快速开始

from nltcache import lru_cache

@lru_cache
def fibonacci(n):
    if n < 2:
        return n
    return fibonacci(n - 1) + fibonacci(n - 2)

print(fibonacci(50))

内存缓存

基于 cachebox 实现,提供多种淘汰策略。所有装饰器都支持带括号和不带括号两种写法,并且原生支持 async def 函数。

包装后的函数暴露底层缓存对象:f.cache 可用于 len(f.cache) 查看条目数,f.cache_clear() 清空。

cache

最简单的 LRU 缓存装饰器,默认 maxsize=1000。

from nltcache import cache

@cache
def add(a, b):
    return a + b

lru_cache

LRU (Least Recently Used) — 淘汰最久未被访问的缓存条目。

from nltcache import lru_cache

@lru_cache(maxsize=500)
def query(sql):
    ...

ttl_cache

TTL (Time To Live) — 缓存条目在超过指定时间后自动过期。

from nltcache import ttl_cache

@ttl_cache(maxsize=1000, ttl=300)  # 300 秒后过期
def get_config(key):
    ...

vttl_cache

VTTL (Virtual TTL) — 与 TTL 类似,但采用惰性淘汰策略,仅在访问时检查并移除过期条目。

from nltcache import vttl_cache

@vttl_cache(maxsize=1000, ttl=60)
def get_status(service):
    ...

lfu_cache

LFU (Least Frequently Used) — 淘汰访问次数最少的缓存条目。

from nltcache import lfu_cache

@lfu_cache(maxsize=1000)
def translate(word):
    ...

fifo_cache

FIFO (First In First Out) — 淘汰最早进入缓存的条目。

from nltcache import fifo_cache

@fifo_cache(maxsize=1000)
def process(data):
    ...

rr_cache

RR (Random Replacement) — 随机淘汰一个缓存条目。

from nltcache import rr_cache

@rr_cache(maxsize=1000)
def compute(x):
    ...

持久化缓存

disk_cachepkl_cache 共享同一套语义:按指定的参数计算缓存键,把结果写到磁盘,跨进程和重启后依然有效。两者都支持 async def 函数。

选择要作为缓存键的参数

from nltcache import disk_cache

# 单个参数
@disk_cache(cache_key="query")
def search(query):
    ...

# 多个参数
@disk_cache(cache_key=["query", "top_k"])
def search(query, top_k=10):
    ...

# 全部参数(省略 cache_key)
@disk_cache()
def search(query, top_k=10, lang="zh"):
    ...

⚠️ 只有被列入 cache_key 的参数会参与缓存键的计算。 未列入的参数即使改变,也会命中同一条缓存并返回旧结果——这是静默的错误结果,不会报错。 如果函数的输出依赖多个参数,请把它们全部列出,或直接省略 cache_key 以全部参数为键。

缓存键的稳定性

缓存键由参数值的规范化编码计算得出,而不是直接 pickle:

  • 集合与字典会先排序再编码,因此不受 PYTHONHASHSEED 影响,跨进程稳定;
  • 类型参与键的计算,1"1"1.0True 互不冲突;
  • 相等的值共享同一条缓存,{"a": 1, "b": 2}{"b": 2, "a": 1} 命中同一项;
  • 无法稳定序列化的值(文件句柄、锁、socket 等)会抛出 UnstableKeyError。 在全参数模式下则降级为"不缓存"并打一条 warning 日志,不会中断调用。

运行时开关与跳过

@disk_cache(cache_key="sql", is_cache="use_cache")
def run_query(sql, use_cache=True):
    ...

run_query("SELECT ...", use_cache=False)  # 跳过缓存,直接执行

is_cache 参数只控制是否读写缓存,不参与缓存键,因此关掉再打开仍会命中同一条目。

cache_key 指定的参数值为 None 时同样跳过缓存(全参数模式下不适用此规则)。

缓存控制 API

被装饰的函数附带一组缓存管理方法:

@disk_cache(cache_key="query")
def search(query):
    ...

search.cache_key("python")  # 该次调用使用的键;跳过缓存时返回 None
search.cache_invalidate("python")  # 删除单条,返回是否存在
search.cache_clear()  # 清空,返回删除条数
search.cache_prune()  # 清理过期条目,返回删除条数
search.cache_close()  # 释放底层句柄,下次调用自动重开
search.__wrapped__  # 未被装饰的原函数

装饰器实例本身也可以作为上下文管理器,退出时关闭它开过的所有存储:

with disk_cache(cache_key="query") as cached:
    @cached
    def search(query):
        ...

disk_cache

基于 diskcache 的 SQLite 存储,支持过期、容量上限和并发访问。新项目优先选择它。

参数 类型 默认值 说明
cache_key str | list[str] | None None 作为缓存键的参数名;None 表示全部参数
cache_dir str | None None 缓存目录,为 None 时按函数标识自动生成
is_cache str "cache" 控制是否启用缓存的参数名
expire float | None 86400 过期时间(秒),None 表示永不过期
size_limit int | None None 总字节数上限,由 diskcache 自行淘汰
**settings 其余参数透传给 diskcache.Cacheeviction_policycull_limit 等)
@disk_cache(cache_key="query", expire=3600, size_limit=512 * 1024 * 1024)
def search(query):
    ...

pkl_cache

每条结果一个 .pkl 文件,按摘要前缀分片存放,采用临时文件 + os.replace 原子写入。适用于结果体积大、希望直接在文件系统里查看的场景。

参数 类型 默认值 说明
cache_key str | list[str] | None None 作为缓存键的参数名;None 表示全部参数
cache_dir str ".cache" 存储 pkl 文件的目录
is_cache str "cache" 控制是否启用缓存的参数名
expire float | None None 过期时间(秒),None 表示永不过期
max_entries int | None None 条目数软上限,按写入时间淘汰最旧的
printf bool False 兼容选项,额外把缓存事件打到 stdout
@pkl_cache(cache_key="filepath", expire=7 * 86400, max_entries=10_000)
def parse_file(filepath):
    ...

cache_dir 的相对路径在装饰时解析为绝对路径,不受运行期 os.chdir 影响。

cache_clear() 只会删除自己写入的分片目录与 .pkl 文件,不会动缓存目录下的其他内容。

反序列化本身不适合处理不可信数据,只应使用当前用户可控的缓存目录。

日志

缓存命中与写入以 DEBUG 级别记录到 nltcache logger:

import logging

logging.getLogger("nltcache").setLevel(logging.DEBUG)

其他

cached_property

重新导出自标准库 functools.cached_property,将方法结果缓存为实例属性。

from nltcache import cached_property

class Config:
    @cached_property
    def settings(self):
        return load_settings()

API 一览

装饰器 存储位置 淘汰策略 支持过期 支持 async
cache 内存 LRU -
lru_cache 内存 LRU -
lfu_cache 内存 LFU -
fifo_cache 内存 FIFO -
rr_cache 内存 随机 -
ttl_cache 内存 TTL
vttl_cache 内存 VTTL (惰性)
disk_cache 磁盘 (SQLite) 容量上限
pkl_cache 磁盘 (pkl) 条目数上限
cached_property 实例属性 - - -

生成器函数(yield)无法被持久化装饰器缓存,装饰时会直接抛 TypeError;请改为返回列表。

从 1.x 升级

2.0 修正了若干会产出错误结果的问题,存在以下不兼容变更:

  1. 缓存键算法变更。 旧缓存不会被读取,首次运行相当于全部重算。旧的 .cache / .disk_cache 目录可以直接删除。
  2. Python 最低版本提升到 3.10。
  3. cache_key 不再是必填参数,省略时以全部参数为键。
  4. vttl_cachettl 之前从未生效(被传给了构造函数,只对初始化数据有效),现已按每条目过期正确实现。
  5. PickleCache / DiskCache 的内部结构重写,_cache_get_cache_file_load_cache_save_cache 等私有成员已移除;公开的 cache_clear() 等方法取代了它们。

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

nltcache-2.0.1-py3-none-any.whl (19.5 kB view details)

Uploaded Python 3

File details

Details for the file nltcache-2.0.1-py3-none-any.whl.

File metadata

  • Download URL: nltcache-2.0.1-py3-none-any.whl
  • Upload date:
  • Size: 19.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.17 {"installer":{"name":"uv","version":"0.11.17","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for nltcache-2.0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 723639113e6425d39bbfd66ff4a9f1ba64d105de864d60fc163b8da42c764f7a
MD5 9e965a0e855bfff1bea03326dd6081ec
BLAKE2b-256 bd9d2531f81018c6a6f41fa98549cf5fb1c9a393b70c59dc4ed57383dce9075c

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

2.0.1 This release

1 file

1.0.15

1 file

1.0.14

1 file

1.0.13

1 file

1.0.12

1 file

1.0.11

1 file

1.0.10

1 file

1.0.9

1 file

1.0.7

2 files

1.0.6

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page