Invalid input of type: CacheKey. Convert to a byte, string or number first:杂记问题处理

本文解决了一个关于Django、Celery和Redis版本兼容性的问题,通过调整到特定版本组合(如django-redis==4.8.0),成功避免了因版本不匹配导致的错误。

问题如下图:

Invalid input of type: ‘CacheKey’. Convert to a byte, string or number first
在这里插入图片描述

  • 在网上搜索了很多,也没有结果,都说是redis数据库版本过高,需要更换成2.10.6,但是 如果redis换成 2.10.6版本的话,celery又会报错,因为 它只支持3.2.0以上版本,很冲突。。。所以绞尽脑汁,在想是否是django-redis的问题,他可是和django和 redis有很大的关系啊!! 所以再三尝试之下,我选择使用 django-redis==4.8.0版本!问题解决
  • 下面是我的一些配置:大家可以参考(我的django比较老,但是以后会更新最新版的django教学,现在先体验老版本与新版的差异)、
    在这里插入图片描述
<think>首先,用户的问题是关于Redis错误:"redis.exceptions.DataError: Invalid input of type: 'Token'. Convert to a bytes, string, int or float first."。他们想了解这个问题产生的原因。 用户提供了几个引用: - 引用[1]:涉及一个错误,输入类型是'dict',需要转换为bytesstring、int或float。 - 引用[2]:提到了类似错误,输入是'CacheKey'。 - 引用[3]:用户尝试使用`pl.hmset('carts_%s' % user.id, new_cart_dict)`,但出错,因为new_cart_dict是列表而非字典,然后他们将new_cart_dict转换为列表。 用户在查找"Token"类型输入的错误原因。错误消息表明Redis期望输入是bytesstring、int或float,但收到了一个'Token'类型的对象,这可能是一个自定义类或对象。 关键点: - Redis的数据存储要求键和值必须是基本类型:字符串(bytes或str)、整数或浮点数。不支持复杂对象如自定义类。 - 错误中的'Token'很可能是一个用户定义的类实例,比如在Python中创建的对象。 可能的原因: 1. **尝试存储非序列化对象**:用户可能尝试直接将一个对象(如Token实例)存入Redis,而没有先序列化为字符串或bytes。 2. **类型错误**:在Redis命令中,如SET或HSET,传递了错误的类型。 3. **序列化问题**:如果使用如pickle或JSON序列化,但序列化不当,可能导致此类错误。 4. **具体场景**:用户在引用中提到使用`pl.hmset`(可能是redis-py的hmset),但出错。'pl'可能是一个Redis连接对象。错误指向输入类型为'Token',类似于引用中的'dict'或'CacheKey'。 从引用[3]中,用户自己解决了一个类似问题:new_cart_dict是列表但应该是字典(或反之);他们转换了类型。所以,核心问题是类型不匹配。 对于'Token'类型: - 在Python中,如果用户有一个Token类(如用于认证),并尝试直接存入Redis,就会出错。 - 解决方案是序列化Token对象为字符串(如JSON字符串)再存储。 回答结构: 1. **解释错误原因**:Redis要求所有数据必须是可序列化的基本类型。'Token'是一个自定义对象,需要转换为bytes、str等。 2. **参考用户引用**:自然地引用提供的信息,如引用[1]和[2]提到类似错误。 3. **提供解决方案**:建议如何修复,如使用JSON.dumps()或pickle.dumps()序列化对象。 4. **系统指令**:使用中文回答;确保LaTeX格式正确;生成相关问题;在回答末尾添加引用标识。 系统指令要求: - 所有行内数学表达式用$...$,但这里可能不需要数学表达式,除非解释数字相关。 - 独立公式用$$...$$,但可能无需。 - LaTeX语法正确。 - 中文回答。 - 生成相关问题。 - 引用的段落末尾添加引用标识,如[^1]。 回答大纲: - 开头澄清错误原因。 - 详细解释基于Redis的要求。 - 参考用户提供的引用。 - 建议修复步骤。 - 结尾生成相关问题。 相关问题生成: 1. 如何序列化Python对象以存入Redis? 2. Redis支持哪些数据类型? 3. 如何处理自定义对象在Redis中的存储? 4. 常见Redis错误及解决方法。 5. 使用JSON vs Pickle在Redis序列化中的比较。 </think>### Redis.exceptions.DataError: 'Token'类型输入无效问题的原因分析 根据您查询的 "redis.exceptions.DataError: Invalid input of type: 'Token'. Convert to a bytes, string, int or float first." 错误,其核心原因是 Redis 存储机制要求所有数据必须是基本类型(如 bytes、字符串、整数或浮点数),而您尝试存储的对象类型为 "Token",这是一个自定义或非基本类型对象。Redis 无法直接处理复杂对象(如 Python 类实例、字典或列表),导致此异常。以下我将逐步分析原因、基于您提供的引用进行说明,并提供解决方案。 #### 1. **错误产生的根本原因** - **Redis 的数据类型限制**:Redis 是一个键值存储系统,仅支持存储序列化的基本数据类型(如 `bytes`、`str`、`int` 或 `float`)。当您使用 Redis 命令(如 `SET`、`HSET`)时,如果输入值是一个对象(如您的 "Token" 实例),Redis 客户端(如 redis-py)会抛出 `DataError` 异常[^1][^2]。 - **"Token" 对象的特性**:在您的场景中,"Token" 很可能是一个自定义类实例(例如用于认证或会话管理的 Python 对象)。Python 中的自定义对象在内存中是复杂结构,Redis 无法直接识别或存储。例如: - 如果您调用类似 `redis_client.set('key', token_object)` 的代码,Redis 会检测到 `token_object` 的类型不是基本类型,从而报错。 - **与引用案例的相似性**:您在引用[1]和[2]中提到的错误(输入类型为 'dict' 或 'CacheKey')与此相同——都是由于传递了非基本类型对象(字典或类实例)导致 Redis 拒绝处理。引用[3]中的用户通过将字典转换为列表解决了类似问题,但这里 "Token" 需要序列化处理[^1][^2][^3]。 #### 2. **具体原因细节** - **类型不匹配**:Redis 命令期望值是可序列化的简单类型,但 "Token" 是一个对象引用。例如,在 Python 代码中: ```python # Hypothetical code causing error token = Token(user_id=123) # 自定义Token对象 redis_client.set('user_token', token) # 错误!直接存储对象会触发DataError ``` 这里,`token` 的类型是 `Token`,而非 `str` 或 `bytes`,违反了 Redis 的输入要求。 - **序列化缺失**:Redis 不原生支持对象存储,您需要先将对象序列化为字符串或 bytes。例如,使用 JSON 或 Pickle 编码: ```python import json serialized_token = json.dumps(token.__dict__) # 将对象属性转为JSON字符串 redis_client.set('user_token', serialized_token) # 正确:存储基本类型 ``` 如果不进行此步骤,Redis 客户端会抛出异常,如引用[3]中用户尝试存储字典时遇到的错误[^3]。 - **框架或上下文影响**:在 Django 或其他框架中,如果您使用缓存或会话管理(如引用[2]提到的 CacheKey),框架生成的中间对象(如 "Token")可能被直接传递到 Redis。检查代码中是否有来自第三方库的 Token 实例被误用[^2]。 #### 3. **解决方案建议** - **序列化对象**:存储前将 "Token" 对象转换为基本类型: - **使用 JSON**(推荐,兼容性强): ```python import json token_dict = vars(token) # 获取对象属性字典 token_str = json.dumps(token_dict) # 序列化为字符串 redis_client.set('user_token', token_str) # 存储 ``` 读取时使用 `json.loads()` 还原。 - **使用 Pickle**(适用于Python专属对象,但有安全风险): ```python import pickle token_bytes = pickle.dumps(token) # 序列化为bytes redis_client.set('user_token', token_bytes) ``` 读取时用 `pickle.loads()`。 - **检查数据类型**:在存储前添加类型检查: ```python if not isinstance(token, (str, bytes, int, float)): token = str(token) # 强制转为字符串,或使用上述序列化方法 redis_client.set('user_token', token) ``` - **框架集成**:如果使用 Django,可以利用内置序列化工具(如 `django.core.serializers`)或确保第三方库正确处理类型,避免直接传递对象到 Redis。 #### 4. **预防措施** - **代码审查**:在调用 Redis 命令前,打印变量类型(如 `print(type(token))`)确认是否为基本类型。 - **错误处理**:添加 try-except 块捕获 `redis.exceptions.DataError`,并自动序列化对象: ```python try: redis_client.set('key', token) except redis.exceptions.DataError: serialized_token = json.dumps(vars(token)) redis_client.set('key', serialized_token) ``` - **参考最佳实践**:类似引用[3]的案例,用户在存储字典前转换为列表解决了问题;此处针对 "Token",序列化是标准做法[^3]。 通过以上分析,错误源于类型不兼容,解决的关键是将对象序列化。如果您提供更多代码上下文,我可以给出更具体的建议。
评论 4
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值