Python字典比较时出现[n chars]奇怪编码类错误求助
刚碰到这种问题的时候我也头大过——明明看着两个字典内容差不多,断言就是失败,还被[n chars]截断得看不到完整差异。别急,咱们一步步拆解解决:
先搞懂[n chars]是什么
这是Python unittest模块的默认行为:当对比的内容太长时,它会把中间相似或重复的部分用[X chars]截断,避免输出刷屏。但这也导致我们看不到完整的差异细节,所以第一步就是获取完整的对比信息。
办法1:关闭unittest的输出截断
在你的测试文件开头加几行代码,把输出长度限制调大,让完整差异显示出来:
import unittest # 设置一个足够大的数值,确保不会截断输出 unittest.util._MAX_LENGTH = 999999
重新运行测试,就能看到两个字典完整的对比内容,直接找到不一样的地方。
办法2:手动打印字典的细节
如果不想修改全局设置,就在断言语句前手动打印两个字典的内容,甚至逐个键对比:
# 先打印完整字典 print("实际数据:", obsolete_data) print("预期数据:", expected_obsolete_data) # 精准对比每个键 all_keys = set(obsolete_data.keys()).union(expected_obsolete_data.keys()) for key in all_keys: print(f"\n键 {key}:") print(f" 实际值: {obsolete_data.get(key, '不存在')}") print(f" 预期值: {expected_obsolete_data.get(key, '不存在')}")
这样能快速定位到哪个键对应的值出了问题——比如你例子里的courses或beers,看起来是同一个对象,但实际可能是不同的实例?
针对自定义对象的问题
看你的报错信息,字典里的值是自定义类的实例(<Category: Test Category>、<Beer: Test Beer>)。Python默认是通过内存地址比较对象的,哪怕两个对象的属性完全一样,只要是不同实例,就会被判定为不相等。
解决这个问题的核心是给自定义类重写__eq__方法,让它按属性值来比较:
class Category: def __init__(self, name): self.name = name def __eq__(self, other): # 先判断是不是同一类实例 if not isinstance(other, Category): return False # 按属性值比较 return self.name == other.name # 同时重写__hash__,不然对象放在集合/字典键里会有问题 def __hash__(self): return hash(self.name)
同理给Beer类也加上对应的__eq__和__hash__方法,这样属性相同的对象就会被判定为相等了。
备选办法:用第三方库辅助对比
如果觉得手动处理麻烦,可以用deepdiff库来做深层对比,它会清晰列出所有差异点,包括对象属性的不同:
from deepdiff import DeepDiff diff = DeepDiff(obsolete_data, expected_obsolete_data) print("差异详情:", diff)
不过这个需要先安装库(pip install deepdiff),如果是项目测试记得把它加入依赖。
总结
先通过关闭截断或手动打印获取完整差异,判断是字典内容真的有不同,还是自定义对象的比较逻辑有问题,再针对性解决就行。
内容的提问来源于stack exchange,提问作者Saša Kalaba

