资讯动态

wrf-python 1.1.3 安装使用指南:从源码编译到 CAPE 插值避坑

发布时间:2026/10/29 16:55:11 来源:尧图企业网站定制
简介wrf-python 1.1.3 是专为 WRF 模式输出数据设计的气象后处理 Python 库支持读取 NetCDF 格式并完成诊断量计算、插值、剖面绘制等典型操作适合大气科学研究者、气象工程师以及有 WRF 使用经验的 Python 开发者。压缩包采用官方打包形式共含 328 个文件其中 222 个 rst 文档和 51 个 py 源码构成主体前者提供 API 说明与使用指南后者包含核心函数与示例脚本另有 18 个 f90 源文件用于构建底层 Fortran 扩展8 个 png 图片展示绘图效果配套的 bat、sh 脚本则帮助 Windows 与 Linux 环境快速安装。整个资源仅 1.3MB结构精炼便于部署。目前已有 2408 人学习下载验证了该库的实用价值。读者可获得官方源码包中完整的库文件、说明文档与构建配置既能直接调用成熟接口也能参考源码与示例掌握 WRF 后处理流程缩短环境配置和开发排错时间。1. wrf-python 是什么气象脚本里的诊断计算黑匣子值不值得下气象模式跑完真正的活才刚开始。wrf-python 1.1.3 这个 tar.gz 源码包是我在本地环境里拆过好几遍的东西——一句话说清楚它是专门吃 WRF-ARW 模式输出wrfout 文件的诊断与插值 Python 库CAPE、CIN、风暴相对螺旋度这类量不用自己写积分公式就能算连 map projection、地形高度这些元数据也一并管了。搞 WRF 后处理的开发者基本都会用到它。原因很直接WRF 输出的风场是模式投影下的格点风位势高度在地形跟随坐标上直接拿 numpy 处理极易算错wrf-python 把这些转换全部封装掉了。下面按我从下载源码包到实际跑通的顺序把依赖、编译、参数和坑都摊开讲。新手能照着装熟手能直接抄参数和避坑清单不用再去翻英文文档踩一遍同样的雷。2. 从 1.1.3 源码包看它能干什么诊断量、插值与坐标换算三块功能tar.gz 解压之后你会看到 wrf/ 目录下一堆 .py 文件外加一个 fortran/ 子目录。1.1.3 的结构决定了它的工作方式Fortran 诊断内核通过 f2py 编译成 Python 扩展上层再包一层面向 netCDF 的接口。所以它不是纯 Python 算法库更像一个「计算黑匣子 气象元数据处理」的组合。理解这一点后面所有报错你都知道该往哪个方向排查——编译期的错看 Fortran 工具链运行期的错看输入变量和全局属性。2.1 诊断量清单从 CAPE、CIN 到风暴相对螺旋度wrf-python 内部维护了一张 varbar 映射表注册了几十个诊断量名称你通过 wrf.getvar(ncfile, 名字, timeidx整型) 去取。我在 1.1.3 里用得最多的几个列在下面变量名物理量备注cape_2d / cin_2d地面 CAPE / CIN多变量返回getvar 只给第一个srhel0-3km 风暴相对螺旋度自动用地形高度做下边界uvmet转成地图正北正东的 u、v多变量返回slp海平面气压由模式气压归算z / pressure位势高度 / 气压常用作插值坐标temp / tk / rh温度 / 虚温相关 / 相对湿度内部做扰动场合成terrain地形高度几乎所有诊断量的底图先看多变量返回这个坑。cape_2d 这个名字在 varbar 里对应 CAPE 和 CIN 两个输出直接 wrf.getvar(ncfile, cape_2d) 只会返回 CAPE并且打一条 warning 告诉你还有 cin_2d 没取想同时拿两个得调底层函数 wrf.cape_2d()。这是个很容易被忽略的约定后面第 4 章会写完整调用。为什么建议直接用这个库而不是自己手写积分WRF 输出的温度是扰动场加上基础态拼出来的CAPE 计算还要考虑上升气块从哪个高度出发、要不要虚温订正、水凝物对浮力的拖曳。这些细节散落在 WRF 源码的 module_diag.F 里手抄一遍非常容易在某个边界条件上抄错。wrf-python 的 Fortran 内核就是从 WRF 诊断模块移植过来的结果和模式自带诊断保持一致这是它最大的价值。2.2 插值与坐标换算vertcross、interplevel 与 ll_to_xy第二块功能是插值。WRF 的水平网格是 map projectionLambert 正形投影最常见垂直层是地形跟随的 eta 坐标直接画图或做站点对比的人都懂这两个坐标是你绕不过去的坎。wrf-python 给了四类工具vertcross 做两点连线之间的垂直剖面返回的二维数组横轴是剖面上的水平格点纵轴是模式层interplevel 把三维变量插到指定等压面注意单位是 Pa700 hPa 要传 7000.0interpz3d 插到等几何高度面做边界层分析时常用ll_to_xy / xy_to_ll 在经纬度和模式格点索引之间换算找台风中心最近的格点就靠它。这几类函数都不需要你手动处理坐标变换它们从 wrfout 文件的全局属性里读 MAP_PROJ、TRUELAT1、TRUELAT2、STAND_LON、MOAD_CEN_LAT 等参数内部用 wrf_proj 模块完成投影换算。这也是为什么我一直强调别用 ncks 之类的工具把 wrfout 裁得只剩变量——全局属性一旦被剥掉ll_to_xy 和 get_cartopy 会全部翻车。细节在第 5 章。2.3 为什么锁定 1.1.3 而不是换 MetPy拆这个包的时候总有人问MetPy 也有 CAPE、也有剖面函数为什么还要 wrf-python我的判断标准是数据出身。MetPy 是通用气象库它不认识 WRF 的地形跟随坐标和 half-level / full-level 约定你用它算 WRF 的 CAPE得先把数据清洗成它认识的格式这个清洗过程本身就是错误高发区。wrf-python 直接消费 wrfout连 eta 层到气压层的换算都替你做了。1.1.3 不是最新版后续有 1.3.x但很多老项目的 setup.py 里直接钉死 wrf1.1.3因为这一版行为最稳定教程和论坛问答也基本按这一版的 API 写的。如果你接手的是一个锁了依赖的老环境照 1.1.3 的 API 写代码基本不会踩文档不一致的坑如果是从零开始的新项目装新版也行但函数调用方式差别不大这篇里的坑位同样适用。3. 把 tar.gz 装进环境两种安装路线与源码编译前的依赖顺序wrf-python 之所以劝退一半新手就因为它带 Fortran 内核。1.1.3 的 tar.gz 里有 fortran/ 源码目录pip 直接装 tar.gz 会在本地现场编译不想跟编译器搏斗就走 conda-forge 的预编译包。这两条路我在不同机器上都走过先把结论给你Linux 服务器上源码编译最干净Windows 上老老实实用 conda。3.1 路线一conda-forge 预编译包省事但版本被频道锁定conda create -n wrf-env python3.8 conda activate wrf-env conda install -c conda-forge wrf1.1.3conda-forge 会把 wrf-python 依赖的 numpy、netcdf4、pint、cartopy 一起装成互相兼容的版本等于帮你把依赖地狱提前排掉了。我一般会顺手把 conda 的频道优先级调成 strict避免和 defaults 频道版本打架。这条路的代价是版本被频道锁定conda-forge 上 1.1.3 对应的 numpy 上限通常比较老1.23 左右如果你项目里其他包要求 numpy 1.24就得考虑路线二或者单独建环境。python 安装环境这件事就一句话气象栈走 conda通用开发栈走 pip别在同一个环境里混两套包管理器装同一批科学计算库。混装的结果往往是 conda 升级一个依赖pip 那边的编译产物就罢工。3.2 路线二从 wrf-python-1.1.3.tar.gz 源码编译tar -xzf wrf-python-1.1.3.tar.gz cd wrf-python-1.1.3 pip install numpy1.24 netcdf4 pint six wrapt matplotlib python setup.py build_ext --fcompilergfortran pip install .这里有三点值得说明。第一setup.py 里的 build_ext 就是调 f2py 编译 fortran 源码--fcompilergfortran 让 f2py 明确用 GNU Fortran机器上没装 gfortran 的话这一步会直接报找不到编译器Linux 下 apt install gfortran 或 yum install gcc-gfortran 即可。第二依赖顺序不能乱先装 numpy 是因为 build 过程要引用 numpy 的头文件先装 netcdf4 是因为 f2py 链接时需要 netCDF 的库路径顺序反了你会看到一堆莫名其妙的 undefined reference。第三numpy 版本先钉在 1.24 以下原因在第 5 章提前说免得你白编译一遍。提示PyPI 上 1.1.3 基本以源码包形式分发没有现成 wheel所以才会出现这份 tar.gz 需要本地编译的场景。如果 setup.py build_ext 走了两分钟还在编译属正常现象Fortran 源码里有几个大函数很吃编译时间别急着 CtrlC。3.3 装完先做三层验证导入、版本、真实数据冒烟python -c import wrf; print(wrf.__version__) python -c from netCDF4 import Dataset; import wrf; print(import ok)# smoke_test.py from netCDF4 import Dataset import wrf nc Dataset(wrfout_d02_2023-08-05_00:00:00) print(wrf.getvar(nc, terrain, timeidx0).shape)import 过了不代表真的能用我见过不少环境 import wrf 正常、一跑 getvar 就崩的案例大多是 Fortran 扩展和 numpy 版本不匹配导致的。所以第三层验证一定拿真实 wrfout 跑一个最轻量的诊断terrain 不涉及垂直积分最快能出 shape 说明编译链接那层是通的。这套三层验证我后来写进了团队的新机器 checklist每次搭环境都强制走一遍省下来的排查时间远大于验证本身花掉的那几分钟。另外提醒一句如果手头暂时没有 wrfout 文件可以先用 ncdump -h 打开任意老备份确认 netcdf4 能正常读文件再进行冒烟。文件打不开的锅不要甩给 wrf-python先检查 HDF5 版本和 netcdf4 库的编译选项。4. 拿来即用的场景读 wrfout 算 CAPE、风切变与垂直剖面装好之后到出结果之间核心就两件事传对 timeidx认准 wrf 返回的是 DataArray 还是 numpy 数组。wrf-python 默认 metaTrue即返回带经纬度坐标的 xarray DataArray这对后续画图友好但如果你要直接做数组运算建议先用 wrf.to_np() 剥一层避免在 DataArray 的维度顺序上栽跟头。4.1 打开文件与 timeidx 约定from netCDF4 import Dataset import wrf ncfile Dataset(wrfout_d02_2023-08-05_00:00:00) print(ncfile.variables[Times].shape) # 先看这个文件有几个时次 terrain wrf.getvar(ncfile, terrain, timeidx0) print(type(terrain)) # xarray.DataArray print(terrain.shape)几乎所有 getvar 的调用都要传 timeidx。约定是0 表示第一个时次-1 或 None 表示最后一个时次整数落在哪个范围就取哪一层。多时次 wrfout 文件里 Time 维度的长度可能和你预想的不一样所以第一步打印 Times 的 shape 是成本最低的自检。我踩过的坑是文件明明是 00 时次的单层输出却传了 timeidx5索引直接越界报错信息还指向了别的地方排查了半小时才反应过来。4.2 算 CAPE/CIN 与风暴相对螺旋度cape, cin wrf.cape_2d(ncfile, timeidx0) # 同时拿两个 srhel wrf.getvar(ncfile, srhel, timeidx0) # 单变量 cape_np wrf.to_np(cape) # 转成 numpy 掩码数组cape_2d 的底层函数签名是 cape_2d(wrfin, timeidx, missingwrf.default_fill, metaTrue)metaTrue 时返回带坐标的 DataArraywrf.to_np 可以剥掉坐标层拿纯数值。注意返回的 cape 是掩码数组模式域外的格点是 masked直接做 max() 之前先确认掩码处理方式否则可能出现一个接近填充值的假极大。SRH 默认从地面到 3km 积分内部自动读地形高度做下边界不需要你再传 terrain。想算 0-1km 的低层螺旋度1.1.3 里没有现成变量常见做法是调底层函数 wrf.srh() 并传 bottom0, top1000.0返回的照样是对应的螺旋度二维场。用底层函数前可以先 help(wrf.srh) 看一遍默认参数比自己猜省事。4.3 把风转到地转坐标uvmet 与风切变uvmet wrf.uvmet(ncfile, timeidx0) # 返回 (umet, vmet) umet, vmet uvmet[0], uvmet[1] # 三维eta 层、y、x pres wrf.getvar(ncfile, pressure, timeidx0) u850 wrf.interplevel(umet, pres, 8500.0) # 850 hPa 的 u v850 wrf.interplevel(vmet, pres, 8500.0) # 850 hPa 的 vWRF 输出里的 U/V 是沿模式投影坐标的格点风画风场或算风切变之前必须先转到地图正北、正东uvmet 干的就是这件事。风切变就是两层地转风矢量差算低层垂直风切变时用 925 与 850 或 925 与 700 的差注意先插到同一气压层再相减不要在 eta 层上直接减——垂直层稀疏的地方跨层直接减会把地形附近的风廓线噪声放大好几倍。4.4 垂直剖面 vertcross 与等压面 interpleveltemp wrf.getvar(ncfile, temp, timeidx0) # 温度eta 层三维 z wrf.getvar(ncfile, z, timeidx0) # 位势高度 cross wrf.vertcross(temp, z, lat(28.0, 32.0), lon(120.0, 121.0)) print(cross.shape) # (水平点数, 垂直层数) pres wrf.getvar(ncfile, pressure, timeidx0) temp_700 wrf.interplevel(temp, pres, 7000.0) # 700 hPavertcross 的 lat、lon 是两个端点坐标剖面在这两点连线方向上展开返回 (水平点数, 垂直层数) 的二维数组。想沿任意折线做剖面可以把剖面拆成多段分别算再拼接wrf-python 一次只支持一条直线段这也是它一个不大不小的边界。拿到 cross 之后用 wrf.to_np() 转出来配合 pcolormesh 画剖面纵轴可以直接用 z 的高度层画比气压层直观。注意interplevel 的 level 参数单位是 Pa700 hPa 写 7000.0写成 700 是最常见的低级错误算出来的结果全在模式顶层附近画图时你会发现整张图花得没法看。血泪经验写完插值代码先打印目标层的平均气压验证再继续往下画。5. wrf-python 常见问题排查五个我实际踩过的坑这一章每条都是「现象 → 原因 → 解决」的记录顺序按出现频率排。前两条集中在安装期后三条集中在运行期照着自己的报错对号入座即可。5.1 Windows 下源码安装报 DLL load failed现象python -c import wrf 报 ImportError: DLL load failed或者 build_ext 时提示无法找到 gfortran。原因Windows 上没有自带 Fortran 编译器f2py 找 MinGW gfortran 的路径非常敏感就算装了 MinGW64 位 Python 和 32 位 gfortran 混用也会在链接期直接炸掉。解决Windows 用户不要走源码编译直接用 conda-forge 的预编译包如果项目强制裸 pip换成 Linux 容器或 WSL 里编译好再导出环境这是我试过最省时间的路径。别在 Windows 上跟编译器较劲那个时间够你跑完两遍 WRF 了。5.2 numpy 1.24 报 np.bool / np.float 不存在现象环境里 numpy 是 1.24 或更新调用 getvar 时抛 AttributeError: module numpy has no attribute bool或者类似的 np.float 报错。原因1.1.3 的部分代码还在用 numpy 旧别名 np.bool、np.floatnumpy 1.24 把这些别名删掉了老库在新 numpy 上跑就崩。解决锁定 numpy1.24比如 1.23.5这是最省事的或者拉源码把出现 np.bool 的地方手改成 bool重新编译一遍。锁版本省心这也是我在 3.2 里先把 numpy 钉住的原因免得编译完才发现跑不起来。5.3 文件被裁剪导致 ll_to_xy 和诊断量翻车现象ll_to_xy 返回的坐标明显不对或者 getvar(temp) 报 KeyError: T_PERT还有些情况不报错只是结果全被 mask 掉。原因wrfout 被 ncks 之类的工具裁剪过全局属性 MAP_PROJ、TRUELAT1/2 丢失投影换算失去基准或者只保留了部分变量扰动场被删掉诊断量无法合成。解决诊断计算一律用原始 wrfout真要裁切片量用 ncks 时加 -h 保留全局属性并确认扰动场变量都在。拿不准的文件先打印 ncfile.ncattrs() 检查关键属性再往下算这一步 30 秒能省后面一小时。5.4 timeidx 索引错位多时次文件取错层现象跑出来的 CAPE 图跟同一天另一张图对不上排查半天发现取的是前一天时次。原因多时次 wrfout 的 Time 维度大于 1timeidx 写了固定数字文件列表更新后索引整体漂移。解决先读 Times 变量确认时次列表再用字符串匹配找到目标时次对应的索引不要写死数字。常见做法是维护一个 {时间字符串: idx} 的映射表批量循环时每次都查表。我在这上面翻过车之后所有批量脚本里都要求先打印本次循环对应的 Times 值再进计算逻辑。5.5 pint 或 cartopy 版本冲突单位与绘图 crs 玄学报错现象wrf.getvar 返回的单位变成很奇怪的字符串或 wrf.get_cartopy 抛 AttributeError不同机器上同一段代码结果不一致。原因wrf-python 依赖 pint 做单位管理、cartopy 做投影1.1.3 的兼容范围比较窄新版本改了接口就会触发这些诡异报错。解决conda-forge 安装时它会锁好配套版本尽量别手动升级这些依赖pip 环境里把 pint 和 cartopy 也钉在解析出来的版本附近。遇到这种问题先 diff 环境别去改业务代码。6. 进阶把诊断流程封装成批处理管线跑完整场个例单时次能算对之后下一步就是把整场个例几十个时次批量跑完。直接写 for 循环不是不行但缺了校验环节错一个时次你都不知道。我的做法是封装一个带 smoke test 的批处理函数先把统计结果落下来再决定要不要画图。6.1 封装 batch_diag 函数import glob from netCDF4 import Dataset import numpy as np import wrf def batch_diag(pattern, out_csvdiag_points.csv): files sorted(glob.glob(pattern)) first Dataset(files[0]) wrf.getvar(first, terrain, timeidx0) # smoke test先验证文件可读 rows [] for f in files: nc Dataset(f) cape, _ wrf.cape_2d(nc, timeidx0) srhel wrf.getvar(nc, srhel, timeidx0) rows.append([f, float(wrf.to_np(cape).max()), float(wrf.to_np(srhel).max())]) np.savetxt(out_csv, np.array(rows, dtypestr), fmt%s, delimiter,) print(done:, len(rows), files)函数开头先对第一个文件做 smoke test文件路径错了、变量名拼错了、全局属性被剥了都会在这一步立刻暴露而不是跑完一半才在结果里发现畸形数据。csv 里同时落文件路径和统计值任何异常时次都能反查到源头。6.2 用统计值校验结果把每个时次的 max 落成 CSV 之后先跟模式自带诊断或官方脚本做一次逐时对比偏差超过阈值立刻定位到具体时次再决定是修代码还是修数据。整套流程的顺序是「先冒烟、再统计、后绘图」统计对不上就不画图避免拿着坏数据出一堆漂亮但没用的图。从那以后我每次跑批量计算都会强制走一遍这个流程先 smoke test再输出统计文件最后才对上某个台风中心点做详细剖面。这套习惯帮我拦下了至少三次数据源错误一次是文件列表混入了另一个域的文件一次是 ncks 裁剪把属性剥了还有一次是时次索引整体偏移。希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑