PAYATHON 2026

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 的证据。

备注:内容仅供参考。