ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

compliance-checker 实战:netCDF 数据文件合规校验与发布流程接入

compliance-checker 实战:netCDF 数据文件合规校验与发布流程接入 简介compliance-checker-4.3.1.tar.gz 是官方发布的 Python 库源码包面向需要开展科学数据合规性检查的开发者可帮助用户快速解析并校验 NetCDF/CDL 等数据结构的描述与内容适用于气象海洋等科研与工程场景。压缩包共 204 个文件体量仅 539KB其中 78 个 .cdl 描述文件承载数据结构定义68 个 .nc 数据文件作为实际校验样例37 个 .py 源码脚本对应库功能与测试逻辑另有 .txt 文档、.j2 模板、.pkg-info 元数据等辅助材料便于分类查阅。目前已有 106 人学习/浏览该资源属于轻量、易上手的官方发布包。借助包内丰富的 CDL/NC 测试样例可以直观理解数据合规检查的判断依据与输出口径结合源码和模板开发者能掌握该库的扩展方式、错误处理机制以及检查规则的配置文件写法方便直接集成到现有数据处理流程中。无论是用于科研数据归档前的质量把控还是基于合规检查能力进行二次开发这份源码包都能提供完整有效的参考。1. compliance-checker 不是代码 lint 器而是数据文件的合规体检工具第一次听说 compliance-checker 的人很容易把它当成一个检查 Python 代码风格的 linter。它其实面向的是数据文件本身用 Python 实现专门检查 netCDF、CSV 这类数据集的元数据和结构是否满足 CF 约定、ACDD、IOOS 等社区标准。4.3.1 这个版本以 tar.gz 源码包形式分发安装时要处理的不仅是 Python 环境还有 netCDF4、lxml 这一串二进制依赖。它的使用场景很具体气象海洋数据发布前的门禁、数据仓库入库前的质量闸门、长期存档数据集的标准符合性审计。适合的人群包括科研数据平台工程师、数据管理岗位以及所有需要批量校验数据文件的技术人员。下面按“装起来、跑起来、查得准、接进流程”四步展开。2. 从 4.3.1 tar.gz 装起compliance-checker 的依赖、国内源与入口验证2.1 解压前先读 PKG-INFOPython 版本与系统库的底线拿到 compliance-checker-4.3.1.tar.gz最忌讳的是直接 pip install 然后等报错。它本质是一个 sdist 源码包先当普通 tar 包拆开看元数据三十秒就能避开大部分环境问题tar -tzf compliance-checker-4.3.1.tar.gz | head -n 20 tar -xOf compliance-checker-4.3.1.tar.gz compliance-checker-4.3.1/PKG-INFO | head -n 40第一条命令列出 tarball 顶层内容确认目录前缀第二条把 PKG-INFO 解到标准输出不用真正落地解压。PKG-INFO 是 setuptools 生成的静态元数据重点看 Requires-Python 和 Requires-Dist 两段。4.x 系列已经全面转向 Python 3直接在 3.8 到 3.11 的干净环境里装最省事系统自带的旧 Python 常常因为缺 venv 模块或 pip 过老在依赖解析阶段就卡住。系统库层面的坑集中在 netCDF4 上。compliance-checker 靠 netCDF4 读文件而 netCDF4 在 x86_64 Linux 上一般能命中 manylinux wheel不需要本地编译一旦 pip 开始现场编译说明你的平台没有对应 wheel得先补 libhdf5-dev 和 libnetcdf-dev。以你手上这份 PKG-INFO 的 Requires-Dist 为准主要依赖大致如下依赖包在 compliance-checker 里的职责最容易踩的坑netCDF4读取 netCDF3/4 与 HDF5 格式数据源码编译时找不到 HDF5/NetCDF-C 头文件lxml解析标准名表、XML 格式约定文档缺 libxml2安装极慢或报编译错jsonschema校验 JSON 配置类内容版本过老导致个别校验行为不一致cf-units单位换算、udunits 语义处理初始化时读不到 udunits 数据库python-dateutil解析时间单位里的日期基准Python 版本跨度过大时行为差异明显2.2 用 pip 从本地 tar.gz 安装并指定国内镜像源整个过程我一般按下面这组命令走Linux 和 macOS 通用# 创建并激活虚拟环境避免弄脏系统 Python python -m venv .venv source .venv/bin/activate python -m pip install --upgrade pip # 本地 tar.gz 不走镜像它的依赖从清华 PyPI 镜像拉取 pip install -i https://pypi.tuna.tsinghua.edu.cn/simple ./compliance-checker-4.3.1.tar.gz先建 venv 是为了不弄脏系统 Python4.3.1 的依赖版本跨度不小隔离环境里翻车成本最低。第四行的 -i 把依赖下载源指到清华 PyPI 镜像国内网络拉 netCDF4、lxml 这类带二进制 wheel 的包会快不少注意本地这个 tar.gz 不走镜像只有它的依赖从镜像下载。如果镜像上没有某个冷门版本把 -i 换成官方源重试即可。Windows 上把激活命令换成 .venv\Scripts\activate如果终端提示 python was not found是解释器没进 PATH用 py 启动器创建环境py -m venv .venv。装完我习惯顺手补一条 pip install --only-binary :all: netCDF4确保拿到的是预编译 wheel在 gcc 版本奇怪的老系统上能省大量调试时间。提示安装日志里看到 Building wheel for netCDF4 就说明在走源码编译这条日志出现时优先回去查系统库而不是反复重装。2.3 装完先验证入口与 checker 列表# 列出当前环境可用的全部 checker 套件 compliance-checker --list-tests # 确认 import 路径和版本 python -c import compliance_checker; print(compliance_checker.__version__)第一条列出当前环境可用的全部 checker 套件第二条确认 import 路径没装歪。命令找不到时检查 venv 的 bin 目录是否在 PATHimport 直接报错时九成是 lxml 或 netCDF4 的二进制和当前 Python 版本对不上回到 2.2 用 --only-binary 重装那两只包。--list-tests 的输出里会看到 cf、acdd、ioos、nccsv 等名字它们就是下一章要讲的 checker。3. compliance-checker 的 checker 套件结构与判定逻辑3.1 内置 checker 各自盯什么compliance-checker 的核心抽象是 checker一个实现统一接口的 Python 类负责对数据集执行一组检查。4.3.1 开箱自带多个 checker彼此独立可单跑可组合。选哪套取决于你的数据要交付给谁、要进哪个数据平台。checker 名称校验对象典型使用场景cf数据集是否符合 CF 约定全局属性、变量属性、坐标气象海洋模式输出发布前acdddiscovery 元数据是否齐全标题、作者、时间范围等数据目录上线、发现服务接入ioosIOOS 数据模板对变量和属性的补充要求海洋观测数据接入nccsvCSV 文件是否按 NCCSV 约定组织无 netCDF 环境的交换数据glider / unidata特定平台或数据流的额外约束水下滑翔机、特定门户数据这几个不是并列的评分项而是不同层次的约定。cf 是最底层最通用的acdd 关心的是“别人能不能在目录里发现这个数据集”ioos 这类在 CF 之上叠加领域要求。所以实际使用经常组合执行compliance-checker -t cf,acdd xxx.nc一次输出两份报告。3.2 一条检查的内部结构编号、优先级与最终判定每个 checker 内部由成百上千条检查组成每条对应约定文档里的某一节。CF 约定要求全局属性必须包含 Conventionschecker 就生成一条编号类似 1.1.1 的检查。每条检查带两个关键属性requirement必须做/应该做/建议做和 priority高/中/低三档。判定逻辑不搞平均分只有高优先级的必须项失败整体校验才判 FAIL中低优先级失败以 warning 形式列出不影响最终判定。这个设计避免了“为几个冷门建议全盘否决一个好数据集”。希望中等级别也算硬性要求时用第五节的 strict 模式。文本报告里每条检查长这样1.1.1 Global attributes must contain Conventions Priority: 1 Result: FAIL Message: Global attribute Conventions is missing四段式结构编号、描述、优先级、结果。编号对应约定文档章节排查时直接翻约定里那一段比读源码快得多。看到 Priority 等级后先判断这条是不是阻塞项再决定修不修这是用好校验器的第一步。3.3 用 -t、-f、-v 控制检查范围与输出四个最常用的参数-l 列出 checker-t 指定 checker逗号分隔多个-f 指定 text/json/html-v 输出更详细的诊断信息。# 同时跑两套约定输出文本报告适合人工阅读 compliance-checker -t cf,acdd -f text demo.nc # 单跑 cf 输出 JSON-v 带上每条检查的 message适合接脚本 compliance-checker -t cf -f json -v demo.nc第一条同时跑两套约定并输出文本报告适合人工阅读第二条单跑 cf 输出 JSON-v 把每条检查的 message 带上适合接脚本。需要共享报告时-f html 生成自包含 HTML 文件直接当附件发出去对方不用装任何东西。4. 实战让一个 netCDF 文件通过 compliance-checker 的 CF 校验4.1 准备一个有典型毛病的 netCDF 测试文件手边没有现成数据时用 netCDF4 现场捏一个。下面这段代码故意漏掉 CF 约定里最常见的几个属性import netCDF4 as nc import numpy as np ds nc.Dataset(demo.nc, w) ds.createDimension(lat, 3) ds.createDimension(lon, 4) lat ds.createVariable(lat, f4, (lat,)) lon ds.createVariable(lon, f4, (lon,)) temp ds.createVariable(temp, f4, (lat, lon)) lat[:] np.array([10.0, 20.0, 30.0]) # 纬度值 lon[:] np.array([110.0, 120.0, 130.0, 140.0]) # 经度值 temp[:] np.random.rand(3, 4) * 20 15 # 模拟温度场 ds.close() print(demo.nc written)三个变量都没写 units两个坐标变量缺 axis 和 standard_name全局没有声明 Conventions。这些正是 CF 检查必然揪出来的点用来观察报告结构刚刚好。4.2 跑 CF 校验并逐段读报告compliance-checker -t cf demo.nc输出分三块头部是 checker 名称与校验标准中间按数据集结构逐条给检查结果末尾是判定汇总。demo.nc 会在全局属性、变量属性、坐标属性三处报 FAIL每条都带编号和修复提示。重点看 Priority: 1 的 FAIL这些是必须修的Priority: 3 的先记下来不阻塞发布。数据集变量变多之后可以用 grep 过滤只看失败项compliance-checker -t cf demo.nc 21 | grep -B 4 -E Result: FAIL提示-t 后面的 checker 名和 -f 后面的格式名都区分大小写写成 CF 会直接报参数错误。4.3 逐个修复并把 FAIL 清零修复顺序固定先全局属性再坐标变量最后数据变量因为后两者的检查会引用全局声明的约定版本。ds nc.Dataset(demo_fixed.nc, w) ds.createDimension(lat, 3) ds.createDimension(lon, 4) lat ds.createVariable(lat, f4, (lat,)) lon ds.createVariable(lon, f4, (lon,)) temp ds.createVariable(temp, f4, (lat, lon)) # 全局声明按哪个版本的 CF 约定校验 ds.setncattr(Conventions, CF-1.8) # 坐标变量补齐单位、坐标轴和标准名 lat.setncattr(units, degrees_north) lat.setncattr(axis, Y) lat.setncattr(standard_name, latitude) lon.setncattr(units, degrees_east) lon.setncattr(axis, X) lon.setncattr(standard_name, longitude) # 数据变量必须声明单位和标准名 temp.setncattr(units, celsius) temp.setncattr(standard_name, air_temperature) lat[:] np.array([10.0, 20.0, 30.0]) lon[:] np.array([110.0, 120.0, 130.0, 140.0]) temp[:] np.random.rand(3, 4) * 20 15 ds.close() print(demo_fixed.nc written)Conventions 声明 CF-1.8 让校验器知道按哪个版本查坐标变量补 units、axis、standard_name 后CF 才能确认它们是合格的经纬度坐标temp 的 units 用 celsiusstandard_name 用 air_temperature。再跑一次 compliance-checker -t cf demo_fixed.nc高优先级 FAIL 应该清零剩下的多半是 cell_methods 这类建议项只影响最佳实践分不影响通过判定。4.4 导出 JSON 供自动化读取# 把报告重定向到文件避免终端刷屏 compliance-checker -t cf -f json demo_fixed.nc cf_report.json # 打印 JSON 顶层键确认结构后再往下取数 python -c import json; djson.load(open(cf_report.json)); print(list(d))第一条重定向报告到文件第二条打印 JSON 顶层键确认结构。不同小版本的 JSON 结构略有差异先 list 再往下取别背结构。拿到结构后在 CI 里按 key 取出 FAIL 数量当门禁。要记住FAIL 是硬门禁warning 是软提示别把两者混成一个总分来卡发布。5. 把 compliance-checker 接进发布流程的三个实用细节5.1 用 strict 模式把 should 项变成硬门禁normal 模式只让高优先级决定 FAIL对外发布的数据集我通常加 -c strict把中等级别的“应该做”也计入失败避免下游拿到缺关键建议属性的数据。compliance-checker -t cf,acdd -c strict -f json release.nc gate.json想把这行直接当 CI 门禁先确认一件小事FAIL 时进程的退出码在你这个 4.3.1 版本上是否为非零。实测确认后写进脚本就一劳永逸如果返回 0就以 gate.json 里的判定内容为准不依赖退出码。5.2 用两次报告对比定位数据退步数据文件发布前把报告存档下个版本重跑后做 diff新增的 FAIL 就是本次改动引入的退步。compliance-checker -t cf -f json release_old.nc old.json compliance-checker -t cf -f json release_new.nc new.json沿用 4.4 的加载方式把两份 JSON 读进来按同一路径取出各自 FAIL 列表做差集。新报告里有、旧报告里没有的 FAIL就是要回去查的改动点。这套对比在数据管线频繁重建时尤其有用比肉眼翻文本报告高效得多。5.3 把修复经验固化成模板函数同一个数据集反复修属性是没效率的。把 4.3 节那套属性写成初始化模板新数据集直接调用让 compliance-checker 在源头就少报错# 模板函数按 CF 约定批量补齐变量属性 def init_cf_attrs(ds, var_map): ds.setncattr(Conventions, CF-1.8) for name, (units, axis, std) in var_map.items(): v ds.variables[name] v.setncattr(units, units) v.setncattr(axis, axis) v.setncattr(standard_name, std)模板化的意义在于把校验器验证过的规则固化进数据生产流程让合规校验从事后救火变成事前规避。本文还有配套的精品资源点击获取
返回列表