xarray 报错 InvalidVersion: Invalid version: 'unknown' 如何解决?
结论
这段堆栈表明,当前 Python 环境中的 Dask 版本信息异常。xarray 检查 Dask 数组类型时,会将 dask.__version__ 传给 packaging.version.Version()。由于版本值为 "unknown",解析时抛出了 InvalidVersion。
先检查实际导入的 Dask,修复对应环境中的安装,再重启 Python 或 Jupyter 内核。仅凭这段报错,无法认定 .nc 文件损坏,也不能保证重装某个指定版本就能解决。
为什么打开文件时正常,显示时才报错?
xr.open_dataset() 返回的 Dataset 可以延迟读取数据,因此打开文件时不一定会读取所有变量,也不会立即执行后续操作所需的全部依赖检查。
在 Jupyter 中单独输入:
ds
会触发 Dataset 的 HTML 展示。这段堆栈中的调用顺序可以简化为:
Dataset._repr_html_()
→ 生成变量预览
→ array_type("dask")
→ 导入 dask 并检查版本
→ Version(dask.__version__)
→ InvalidVersion: Invalid version: 'unknown'
"unknown" 不是 packaging 接受的版本字符串。所以,即使没有主动使用 Dask 分块,xarray 在判断数组类型时也可能触发这个错误。
这段堆栈能确定的是展示失败的原因。如果某项数据运算也报错,还需要查看该运算的堆栈,确认是否同样停在版本解析处。
第一步:在报错的内核中检查 Dask
在出现问题的 Notebook 或 Python 会话中执行:
import sys
import dask
import xarray as xr
from importlib.metadata import PackageNotFoundError, version
print("Python:", sys.executable)
print("xarray:", xr.__version__)
print("Dask module:", dask.__file__)
print("Dask __version__:", repr(dask.__version__))
try:
print("Dask distribution version:", version("dask"))
except PackageNotFoundError:
print("未找到 Dask 的安装元数据")
检查输出时,注意以下信息:
sys.executable是否属于预期的 Conda 或虚拟环境。终端安装依赖时使用的环境,可能与 Notebook 内核不同。dask.__file__是否指向该环境的site-packages。如果指向项目目录中的dask.py或自建的dask文件夹,应先解决同名遮蔽。dask.__version__是否确实为"unknown"。如果安装元数据与模块版本不一致,或者元数据缺失,需要继续排查,但这些现象还不足以确定具体原因。
也可以不打开文件,单独验证版本解析:
import dask
from packaging.version import Version
print(Version(dask.__version__))
如果这里出现相同异常,就能确认该错误可以脱离 NetCDF 文件独立复现。
接下来可以排查安装是否完整、源码安装时是否存在版本生成问题,以及混用包管理器后是否留下了残余文件。当前堆栈无法区分这些原因。
第二步:修复实际使用的环境
发现同名模块遮蔽时,先重命名对应文件或文件夹,再重启内核。重装依赖不会改变 Python 优先导入本地同名模块的行为。
导入路径正确时,按该环境原有的包管理方式修复 Dask,从下面两种方式中选择一种。
使用 Conda 管理依赖的环境
在终端中执行,将 your_env 替换为 Notebook 内核对应的环境名:
conda install -n your_env --force-reinstall dask-core dask
Conda 将 Dask 的核心代码放在 dask-core 包中,修复时也需要检查这个包。尽量沿用环境原有的 channel 配置,并在安装前查看 Conda 列出的依赖变更。
使用 pip 管理依赖的环境
可以在当前 Notebook 中通过实际使用的解释器运行 pip,避免将包装到另一个 Python 环境:
import subprocess
import sys
subprocess.check_call([
sys.executable,
"-m",
"pip",
"install",
"--upgrade",
"--force-reinstall",
"dask[array]",
])
如果项目固定了依赖版本,应按项目约束重新安装,不必直接升级到最新版本。
安装完成后,重启 Jupyter 内核或 Python 进程,再重新导入。当前进程可能仍保留旧模块,xarray 也可能缓存了依赖检查结果,因此仅重复运行 import dask 不足以验证修复是否成功。
第三步:先验证版本,再验证数据读取
重启后,先检查 Dask 能否正常导入,以及版本能否正常解析:
import dask
import dask.array
from packaging.version import Version
print("Dask path:", dask.__file__)
print("Dask version:", Version(dask.__version__))
确认不再报错后,再打开文件,读取一个变量的小切片:
import xarray as xr
with xr.open_dataset("path/to/file.nc") as ds:
print(ds)
if ds.data_vars:
name = next(iter(ds.data_vars))
var = ds[name]
# 每个维度只取第一个位置,避免直接加载整个变量。
sample = var.isel({
dim: slice(0, 1)
for dim in var.dims
}).load()
print(sample)
这段代码分别检查 Dataset 展示和部分数据的实际读取。小切片读取成功,只能说明这部分数据正常,不能证明整个文件的所有变量都没有问题。如果版本检查通过后又出现后端或文件读取异常,应根据新的堆栈继续排查。
哪些做法不能可靠解决这个错误?
chunks=None 控制数据是否使用 Dask 分块,但这段堆栈涉及的展示代码仍会查询 Dask 数组类型,因此它不能保证绕过问题。
切换为文本展示也不保证有效:
xr.set_options(display_style="text")
文本和 HTML 展示可能共用变量格式化逻辑,这种切换只能作为观察手段。
不要手动给 dask.__version__ 赋一个看似合法的值,也不要修改 xarray 源码跳过检查。依赖可能根据版本选择不同逻辑,伪造版本会掩盖实际的安装问题。当前错误也没有提供需要更换 NetCDF 引擎或降级 packaging 的证据。
备注:内容仅供参考。
