Python将缓存pandas DataFrame传入缓存函数报unhashable type错误如何解决
报错的核心原因是cachetools的@cached装饰器默认会将函数的所有入参进行哈希运算生成缓存键,而pandas的DataFrame属于可变对象,本身不支持哈希操作,因此会触发你遇到的类型错误。
以下是两种可实现需求的解决方案:
方案1:自定义缓存键生成函数(适配function2需要接收任意来源DataFrame的场景)
可以用pandas内置的pd.util.hash_pandas_object方法计算DataFrame的唯一哈希值,再给@cached装饰器指定自定义的key生成逻辑,绕过默认的入参哈希规则。
修改后代码如下:
from cachetools import cached, TTLCache import pandas as pd cache = TTLCache(10, 1000) @cached(cache) def function1(): df = pd.DataFrame({'one': range(5), 'two': range(5,10)}) return df # 自定义function2的缓存键生成规则 def generate_func2_key(df): # 计算DataFrame的哈希值,转成可哈希的元组格式作为键的一部分 df_hash = tuple(pd.util.hash_pandas_object(df)) return (df_hash, ) @cached(cache, key=generate_func2_key) def function2(df): var1 = df['one'] var2 = df['two'] return var1, var2 def function3(): df = function1() var1, var2 = function2(df) print('this is var1[0]: '+str(var1[0])) print('this is var2[0]: '+str(var2[0])) function3()
方案2:调整函数调用结构(适配function2的输入仅来自function1的场景)
如果function2的DataFrame固定由function1生成,可以直接在function2内部调用function1,不需要把DataFrame作为入参传入,从根源上避免可变对象哈希的问题。
这种方案逻辑更简单,性能也更高,不需要每次计算DataFrame的哈希值,修改后代码如下:
from cachetools import cached, TTLCache import pandas as pd cache = TTLCache(10, 1000) @cached(cache) def function1(): df = pd.DataFrame({'one': range(5), 'two': range(5,10)}) return df @cached(cache) def function2(): # 直接内部调用已经加了缓存的function1,df未缓存时会自动生成,已缓存直接取缓存值 df = function1() var1 = df['one'] var2 = df['two'] return var1, var2 def function3(): var1, var2 = function2() print('this is var1[0]: '+str(var1[0])) print('this is var2[0]: '+str(var2[0])) function3()
两种方案都可以实现你需要的效果:df、var1、var2均会被缓存,仅当df缓存过期/不存在时才会重新生成df,再同步生成新的var1、var2并缓存。
内容的提问来源于stack exchange,提问作者bart cubrich
相关产品推荐
相关产品推荐

