使用amazon-dax-client==2.0.0时遇TypeError: unhashable type: 'collections.OrderedDict'
解决DAX客户端batch_get_item时的TypeError: unhashable type: 'collections.OrderedDict'
问题背景
使用amazon-dax-client==2.0.0和Python 3.8.7调用batch_get_item接口时,生产环境持续出现以下错误,但测试环境无法复现:
TypeError: unhashable type: 'collections.OrderedDict'
关键堆栈跟踪信息:
GetItemIssue, batch_keys:{'beauty_mapping_details': {'Keys': [{'id': '123'}, {'id': '345'}, {'id': '556'}, {'id': '777'}, {'id': '111'}]}} tableName:beauty_mapping_details Traceback (most recent call last): ... File "/home/ubuntu/.local/lib/python3.8/site-packages/amazondax/AttributeValueDecoder.py", line 32, in deanonymize_attribute_values values = dict(zip(attr_names, attr_values)) TypeError: unhashable type: 'collections.OrderedDict'
原因分析
错误触发点在DAX客户端的AttributeValueDecoder.deanonymize_attribute_values方法中:当代码尝试用dict(zip(attr_names, attr_values))构建字典时,attr_names列表中混入了OrderedDict类型的元素。由于字典的key必须是可哈希类型,而OrderedDict不具备哈希特性,因此抛出该异常。
生产环境独现问题的可能原因:
- 生产环境DynamoDB表
beauty_mapping_details中存在属性名是OrderedDict类型的异常数据,测试环境无此类数据。 amazon-dax-client==2.0.0版本存在序列化/反序列化bug,仅在特定数据结构下触发,测试场景未覆盖。- 生产环境DAX缓存中留存了旧的异常数据,导致解析失败。
解决方案
1. 升级DAX客户端版本
amazon-dax-client==2.0.0是较旧版本,官方后续版本已修复大量数据解析类bug。执行以下命令升级到最新稳定版:
pip install --upgrade amazon-dax-client
2. 预处理返回数据,转换OrderedDict为普通dict
在获取DAX响应后,递归遍历数据结构,将所有OrderedDict转换为普通dict:
from collections import OrderedDict def normalize_data(obj): if isinstance(obj, OrderedDict): return {k: normalize_data(v) for k, v in obj.items()} elif isinstance(obj, list): return [normalize_data(item) for item in obj] elif isinstance(obj, dict): return {k: normalize_data(v) for k, v in obj.items()} return obj # 调用batch_get_item后处理结果 response = dynamo_client.batch_get_item(RequestItems=batch_keys) response = normalize_data(response)
3. 检查并修复生产环境数据
排查beauty_mapping_details表中的异常条目,找到属性名是OrderedDict的记录,将其修正为合法的字符串属性名。
4. 临时修改DAX客户端解析逻辑(紧急场景)
如果无法立即升级版本,可临时修改AttributeValueDecoder.py文件,在创建字典前处理attr_names中的OrderedDict:
# 在amazondax/AttributeValueDecoder.py的deanonymize_attribute_values方法中添加处理逻辑 from collections import OrderedDict processed_attr_names = [] for name in attr_names: if isinstance(name, OrderedDict): # 将OrderedDict转换为可哈希的元组 processed_attr_names.append(tuple(name.items())) else: processed_attr_names.append(name) values = dict(zip(processed_attr_names, attr_values))
注意:此为临时方案,后续升级客户端时需移除该修改。
内容的提问来源于stack exchange,提问作者Ruchika Garg
相关产品推荐
相关产品推荐

