基于Pickle的通用Get/Set函数实现及**kwargs传递方法咨询
解答
问题1:更优实现或现成包推荐
现成包方案
最实用的是joblib,它比原生pickle更适合处理大对象(比如numpy数组、机器学习模型),并且内置了成熟的缓存逻辑,无需手动编写文件判断代码:
from joblib import Memory import datetime as dt # 初始化缓存存储目录 memory = Memory(location='Pickles', verbose=0) # 用装饰器标记需要缓存的函数 @memory.cache def run_some_function_to_build_object(): # 此处是耗时的对象创建逻辑 return obj
每次调用这个函数时,joblib会自动检查对应参数的缓存文件是否存在:存在则直接返回缓存对象,不存在则执行函数并将结果持久化。它还会根据函数参数自动生成唯一缓存键,适配带参数的场景。
自定义实现优化点
如果坚持自己实现逻辑,可以做这些改进:
- 把文件路径生成抽成独立函数,避免重复拼接:
def _get_pickle_path(name, date): return f'Pickles/{name}_{date.strftime("%y-%b-%d")}' - 扩大异常处理范围,比如捕获
pickle.UnpicklingError来处理损坏的缓存文件; - 添加
force_refresh参数,允许强制重新生成对象(比如当天需要更新数据的场景)。
问题2:kwargs传递的可行性
你写的obj = function_as_an_object(**kwargs)完全可行,但需要注意几个细节:
- 参数匹配检查:确保传入的
function_as_an_object能接受这些kwargs,否则会抛出TypeError。可以用inspect模块提前验证:import inspect def _dill(name, function_as_an_object, date=dt.date.today(), **kwargs): # 检查函数是否支持传入的参数 sig = inspect.signature(function_as_an_object) try: sig.bind_partial(**kwargs) except TypeError as e: raise ValueError(f"函数不支持传入的参数:{e}") from e # 后续原有逻辑... obj = function_as_an_object(**kwargs) - 扩展通用性:如果需要支持位置参数,可以改成同时接受
*args, **kwargs,覆盖更多场景:def _dill(name, function_as_an_object, date=dt.date.today(), *args, **kwargs): try: path = f'Pickles/{name}_{date.strftime("%y-%b-%d")}' with open(path, 'rb') as f: obj = pickle.load(f) return obj except FileNotFoundError: obj = function_as_an_object(*args, **kwargs) with open(path, 'wb') as f: pickle.dump(obj, f) return obj - 缓存键适配:如果函数参数会影响对象生成,当前文件名只包含日期和name,会导致不同参数生成的对象被覆盖。这种情况下,建议把参数的哈希值加入文件名,或者直接用
joblib自动处理。
内容的提问来源于stack exchange,提问作者keynesiancross
相关产品推荐
相关产品推荐

