xarray 属性含嵌套数组时,identical 报真值不明确
DataArray 数据相同,但 attrs 中的字典保存多元素 NumPy 数组时,identical 和合并属性可能失败。分开验证数据与属性,或明确调整属性结构。
两个 DataArray 的值、坐标都相同,a.identical(b) 却报 The truth value of an array with more than one element is ambiguous。如果 attrs 中有一个字典,字典里又放着多元素 NumPy 数组,应检查属性比较路径。
xarray 2026.9.0 对顶层数组属性和列表有专门等价判断,但嵌套字典可能落到普通 ==。字典比较内部又要求数组比较结果能变成单个布尔值,因而抛异常。xr.testing.assert_identical() 同样可能失败;合并时,drop_conflicts 还可能把实际上相同的属性删除。
先判断是数据不同,还是属性比较失败
例如两边都有如下属性结构:
attrs = {"calibration": {"coeffs": np.array([1.0, 2.0])}}
这里假定已有 import numpy as np。两个分别创建的数组内容相同,不代表 Python 字典能够直接比较它们。不能通过让两边共享同一个属性对象来“修好”比较,那会改变共享和修改关系,还可能只是触发对象身份相同的快捷分支。
如果只需定位问题,可先比较数据与坐标,再按明确的属性结构比较数组:
import numpy as np
import xarray as xr
xr.testing.assert_equal(a, b)
np.testing.assert_array_equal(
a.attrs["calibration"]["coeffs"],
b.attrs["calibration"]["coeffs"],
)
assert_equal 不验证 attrs,上面第二步也只覆盖这一项已知数组。应用还有其他属性、维度标签或自定义缺失语义时,需要逐项补全;这段定位代码不能当作任意对象 assert_identical 的完整替代。
允许调整元数据结构时,把数组放到明确层级
若属性模式由应用自己控制,可把数组变成命名清楚的顶层属性,例如 calibration_coeffs,将其他标量属性保留在既定位置。顶层 ndarray 会进入 xarray 已有的数组比较路径;但这会改变元数据结构,所有读取它的导出、合并和业务代码必须一起适配。
多维、带坐标或需要参与计算的标定数据,也可能更适合作为变量保存。这个选择取决于数据模型,不能为了一个比较异常就把所有 attrs 一律搬进 data_vars。
若结构不能改,应使用应用定义的数组安全比较规则,在完成全部元数据验证后再决定合并政策。combine_attrs="override" 会选择一方属性,只有明确接受该政策且已核对冲突时才能使用;直接切换过去,会隐藏真实差异。
不要在异常外套 any 或 all
异常发生在嵌套字典比较内部,外层 np.all(a.identical(b)) 拿不到一个可归约的结果。捕获 ValueError 后一律返回 False,也会把相等对象判成不等;合并时静默丢属性可能进一步丢掉标定信息。
验收覆盖数组相同、数组不同、缺少属性键、数组形状不同,以及双方分别持有独立数组的情况。若最后要写 NetCDF 或 Zarr,还须按目标格式验证属性序列化;内存里的比较成功不表示任意嵌套字典都能保存并原样恢复。
正式 2026.9.0 仍有上述等价比较分支。后续版本若增加递归处理,应以相同和不同的属性样本复查返回值、断言以及合并后的属性,不能只确认不再抛异常。


