简介:这是一份面向气象研究与数值模式应用者的Python库资源,即wrf-python 1.1.3官方发行版。该库用于读取、诊断和可视化WRF模式输出,支持Python 3环境下的风场、温度、降水等常见变量计算与制图,适合科研人员及研究生在模式后处理场景中直接部署使用。资源包共328个文件,整体约1.3MB,核心以Python源码和Fortran程序为主,同时包含rst文档、辅助脚本、配置文件及测试数据等,便于用户了解库结构、检查构建参数并完成本地安装。该版本适配常见Python环境,安装配置相对简洁。目前已有2408人学习下载,属于较为常用的小型库包;获取后可在离线环境快速配置依赖,省去自行编译与查找历史版本的时间,尤其适合需要复现论文实验或搭建气象数据批处理流程的开发场景。1. wrf-python 是什么:把 WRF 后处理从手写循环里解放出来WRF 模型的输出文件,几乎每个做过气象数值模拟的人都被它折磨过:几千个变量、坐标混乱、动不动就三四百 MB 的 NetCDF。wrf-python 这个库就是为了把这种折磨降到最低——它把过去 NCL 里那套现成的气象诊断函数(算露点、算海平面气压、算雷达反射率)原样搬进了 Python,用 getvar 一行就能拿到变量,大数组计算全程走 numpy,不用手写循环。下面围绕 wrf-python 1.1.3 这个版本,把从安装、读数据、算诊断变量到坐标换算的完整路径讲清楚。适合三类人:跑 WRF 模式的人、做气象数据后处理的人,以及刚开始用 Python 替代 NCL 的学生和工程师。2. 安装 wrf-python 1.1.3:依赖顺序、环境隔离和 tar.gz 的三种装法安装这一关过不去,后面全都白搭。wrf-python 不是纯 Python 包装的库,它的核心计算代码是 Fortran 编译出来的扩展模块,pip 在装的时候要现场编译,所以环境对不对、编译器有没有,直接决定你接下来是顺利 import 还是面对一屏报错。这一章我把最稳的安装路径拆开讲,从建环境到验证一次性走通。2.1 先建一个独立环境,别往 base 里塞很多人拿到 tar.gz 直接 pip install 到默认环境,结果过几天装了个深度学习框架,numpy 被降级,wrf-python 突然开始报版本冲突。wrf-python 对 numpy、scipy 的版本是敏感的,所以我一般建议项目开始时就用 conda 单独建一个环境,后面重装、换版本都不用担心影响其他项目。顺手把 python 版本选在 3.9 或 3.10 这类比较稳的版本区间。# 创建独立环境并激活 conda create -n wrf python=3.9 -y conda activate wrf参数说明:-n wrf给环境起名叫 wrf,可以换成你喜欢的项目名;python=3.9指定解释器版本,建议别一上来追最新版,部分编译型科学计算库在新版本 Python 刚发布时还没有预编译轮子,现场编译会给你多添一堆麻烦。激活之后命令行会出现(wrf)前缀,后面所有安装操作都锁在这个环境里。为什么强调隔离?因为 wrf-python 装的是带 Fortran 扩展的包,重装一次等于重新编译一次,编译要花几分钟到十几分钟;如果环境干净,一次装对,后面不用反复折腾。我见过有人在 base 环境里反复翻车之后,干脆把所有气象库全装进独立 conda 环境里用,反而再没出过兼容问题。另外,如果你后处理时还要装 cartopy、xarray 这些库,也建议都在同一个环境下解决,它们对 numpy 的版本要求往往互相拉扯,环境隔离是唯一的后悔药。2.2 三种方式把 tar.gz 装上拿到 wrf-python-1.1.3.tar.gz 之后,最常见做法是直接交给 pip 处理。它会把包解压、跑 setup.py、编译扩展模块,再装进当前环境。命令就一行:# 在 tar.gz 所在目录下执行 conda activate wrf pip install ./wrf-python-1.1.3.tar.gz这里的.前缀是告诉 pip 从本地文件安装,不是从公开包索引拉取。pip 会自动解析依赖,numpy、scipy、matplotlib、netCDF4 这些如果环境里没有,它会顺带安装。不过我建议先把依赖用 conda 装好再装这个库,因为 conda 处理 netCDF4 和底层 HDF5 的二进制兼容性比 pip 稳得多,这一点在第 4 章避坑部分会展开讲。第二种方式是复古的源码安装:解压后直接跑 setup.py。这条路径适合你想在安装前改编译参数,或者 pip 处理 source 包出问题的时候用来定位原因:# 方式二:解压后手动 setup 安装 tar -xzf wrf-python-1.1.3.tar.gz cd wrf-python-1.1.3 python setup.py install第三种方式是 pip 直接从公开包索引安装指定版本,不需要本地包文件。适合你只是想要这个版本、不需要改任何代码的场景:# 方式三:从索引直接拉取指定版本 pip install wrf-python==1.1.3三种方式最终装出来的代码是一样的,区别在于包从哪来、构建过程你可控到什么程度。第一次装建议用本地 tar.gz 的方式,因为包文件就在手边,构建失败能直接看到是哪个环节出错,也方便反复重试。在内外网隔离的服务器或者内网集群上,本地 tar.gz 几乎是唯一可靠的路径:在外网机器上提前把包下载好,再传进内网用pip install ./wrf-python-1.1.3.tar.gz装,完全不依赖运行时网络。无论哪种方式,Linux 上都要有 gfortran,macOS 上要有基于 gcc 的 Fortran 编译器。装编译器的命令在这里,Windows 用户建议直接换 WSL 环境来做,省得跟 MSVC 较劲:# Debian / Ubuntu 系 sudo apt install gfortran # macOS(需先有 Homebrew) brew install gccgfortran 就是用来编译 wrf-python 里 Fortran 源文件的,装好之后可以用gfortran --version验证。没有编译器时,pip 一般在构建阶段直接报gfortran: command not found或者类似错误,很多人误以为包坏了,其实只是编译器没装,装完重新 pip install 一次就好。2.3 安装完的快速自检装完别急着跑业务脚本,先做 30 秒自检:确认 import 成功、版本正确。执行下面这条命令:python -c "import wrf; print(wrf.__version__)"正常会打印出类似1.1.3的版本号。如果 import 报错,把报错信息里提到的缺库逐个补上,再重新 import。接下来用一个真实的 WRF 输出文件做最小读取测试,确保 getvar 能正常拿到变量:import netCDF4 as nc import wrf ds = nc.Dataset('wrfout_d01_2023-07-01_00:00:00') slp = wrf.getvar(ds, 'slp', timeidx=0) print(slp.shape, slp.units)wrf.getvar第一个参数是打开的 Dataset 对象,第二个是变量名缩写,timeidx=0表示取第一个时次。返回的 slp 对象自带单位、坐标这些元数据,直接 print 就能看到关键信息。如果能打印出类似(97, 145)和hPa,说明安装和基本调用都过了关,下一步就可以去算正经变量了。3. 上手核心操作:用 getvar 读 WRF 输出并算诊断变量装好之后,真正值钱的部分就是把工作流跑起来。WRF 输出文件里变量很多,但日常后处理真正高频用到的核心操作其实就三类:读变量、算诊断量、做层次插值。这一章按这个顺序给你一套可以照着改的小作业。把下面代码里的文件名换掉,基本就能直接跑出结果。3.1 读文件之前先看结构,别当黑匣子很多人打开 wrfout 文件就直接ds.variables['T'][:]一把梭,结果后面画图时坐标对不上。WRF 输出的网格是 Arakawa-C 格点,不同变量定义在格点上,而且文件里的维度一般是(Time, south_north, west_east),跟常见的(lat, lon)习惯不完全一样。所以我拿到文件第一件事是打印维度和形状,把坐标变量名记下来。import netCDF4 as nc ds = nc.Dataset('wrfout_d01_2023-07-01_00:00:00') print(ds.dimensions.keys()) print(ds.variables['T'].shape) print(ds.variables['T'].dims) print(ds.variables['XLAT'][0, 0, 0], ds.variables['XLONG'][0, 0, 0])ds.dimensions.keys()告诉你文件里有几个维,通常是 Time、south_north、west_east,如果模拟开了土壤方案,还会有 soil_levels 之类的竖向维。T 的 shape 里第一个轴是时次,后面两个是空间维。XLAT 和 XLONG 是每个格点的经纬度,维度里通常带 Time 轴,[0, 0, 0]是第一个时次、第一个格点的经纬度。先确认这些,后续所有操作都不容易跑偏。为什么推荐 getvar 而不是直接读原始变量:WRF 输出里部分变量是压缩存储或者带缺测标记的,直接ds.variables[...]读出来可能带着原始单位,比如位温没做数值转换,风场没旋转回地球坐标。getvar 会在读出来的同时补上单位换算、缺测值处理,还自动带上坐标信息。这就是它存在的意义。对新手来说,判断一个变量该不该用 getvar,一个简单标准是:你打算画图或者做物理量诊断,就一律走 getvar;只是读数据做切片、算均值,可以直接读 raw 变量。3.2 getvar 一行拿诊断变量:slp、td、uvmet10、dbzwrf-python 把气象分析里最常用的一批物理量封装成了“快捷方式”,用缩略名就能直接取。下表是几个我用的最频繁的:变量名物理含义典型用途slp海平面气压地面天气图分析td露点温度湿度分析、对流潜势判断uvmet1010 米风,已旋转到地图投影地面风场图dbz雷达反射率模拟回波与实况对比theta位温层结分析geop位势高度高空形势分析对应代码很简洁:import netCDF4 as nc import wrf ds = nc.Dataset('wrfout_d01_2023-07-01_00:00:00') # 取第一个时次的海平面气压 slp = wrf.getvar(ds, 'slp', timeidx=0) # 取最后一个时次的雷达反射率,timeidx 用 -1 dbz = wrf.getvar(ds, 'dbz', timeidx=-1) # 取10米风,返回的是 u、v 分量组成的风对象 uvmet10 = wrf.getvar(ds, 'uvmet10', timeidx=0) print(slp.shape, slp.units) print(dbz.shape, dbz.units) print(uvmet10.shape, uvmet10.units)参数说明:timeidx是时次索引,0 是第一个、-1 是最后一个;如果传None会返回全部时次的数组,但内存占用明显上去,几十个时次的 WRF 输出文件建议按需取。uvmet10返回的是已经旋转到地图投影的风分量,不是格点坐标下的原始 U/V;想单独拿 u 或 v,可以取返回对象的第一维:u10 = uvmet10[0],v10 = uvmet10[1]。这些返回对象是 xarray DataArray(如果环境里装了 xarray)或 wrf 自带的扩展数组,都带units、coordinates属性。你也可以用wrf.to_np把它转成 numpy ndarray 去配合其他库计算。注意:转 numpy 会丢掉单位信息和坐标,所以画图用原对象,做算术运算用 numpy,这是常见的分工方式。3.3 把模式层数据插值到等压面WRF 模式输出用的是地形追随坐标,物理层高度随地形起伏。做天气分析时,通常要把要素插值到 850 hPa、500 hPa 这些固定等压面上。wrf-python 的interplevel就是干这个的:# 先取气压场和温度场(模式层) pressure = wrf.getvar(ds, 'pressure', timeidx=0) tk = wrf.getvar(ds, 'tk', timeidx=0) # 插值到 850 hPa(pressure 默认单位是 Pa,850 hPa 写 85000) temp850 = wrf.interplevel(tk, pressure, 85000) print(temp850.shape, temp850.units)注意:interplevel的目标层次单位要和气压场一致。wrf.getvar(ds, 'pressure', timeidx=0)返回的 pressure 单位是 Pa,所以 850 hPa 要写 85000。如果你在 getvar 时传了vert_units='hPa',那么 pressure 字段就会变成 hPa,interplevel 里传 850 就可以了。写错单位不会报错,但插值结果会整体偏移,画出来的图看着没啥大问题,数值全是错的,属于典型的“数据正常但不物理”的坑。如果你需要一次性算多个层次,或者需要同时插值温度和相对湿度,可以改用vinterp。vinterp的用法更像“垂直再分析”:给一批层次,按气压或者高度批量插值。常见做法是先把层次列表定好,再循环调interplevel,或者直接上vinterp一次处理完。前者逻辑简单、单层出错好查,后者性能更好。我一般数据量小用interplevel,几十个时次以上用vinterp批量处理。4. 五个高频坑:从安装报错到数据读取翻车排查下面这五个坑,是我和身边几个做模拟后处理的人在不同项目里真实踩过的,覆盖安装和数据读取两条主线。每个都按“现象、原因、解决”拆开,你对照自己的报错就能定位。有些问题看起来像是库里写错了,实际上多半是环境或者单位没有对齐。4.1 pip 安装报 gfortran: command not found现象:pip install ./wrf-python-1.1.3.tar.gz执行到一半,控制台刷出一堆编译日志,最后抛出一个找不到 gfortran 的错误,构建失败。原因:wrf-python 的扩展模块是 Fortran 写的,pip 安装时调用本机编译器现场编译。机器上没有安装 Fortran 编译器,或者编译器不在 PATH 里,就会卡在这一步。这不代表包坏了,只是构建环境缺件。解决:先确认编译器有没有,再重装。Ubuntu/Debian 执行sudo apt install gfortran,macOS 执行brew install gcc。装完用gfortran --version验证版本输出。如果是在内网离线环境,提前把 gfortran 的安装包准备好,再走本地 tar.gz 安装流程。装完编译器之后,直接重跑刚才的 pip install 就行,不需要删除什么残留文件。4.2 getvar 返回数组的维度顺序和文件对不上现象:用 getvar 拿 slp,打印 shape 是(145, 97),但直读ds.variables['SLP']的 shape 是(1, 97, 145)。画图时经纬度对不上,地图上出现一个躺倒的天气系统。原因:wrf-python 内部做了维序重组。getvar 默认吃掉timeidx指定的单时次,把 Time 维压缩掉;另外 uvmet 家族返回的数组第一轴是风的分量(u、v),不是时次。直接拿原始文件的维度顺序去套返回值,空间维就反了。解决:不要用猜的。对返回对象打印shape、units、dims,确认顺序后再喂给画图函数。需要做数组运算时,用wrf.to_np转成 numpy 后特别留意维序,必要时用numpy.transpose调整。养成先看 shape 再动手的习惯,能省掉大量返工。我自己的习惯是每个新变量第一次取出来时,都把它和 raw 变量的维度对照打印一遍,后面就不会再犯。4.3 自己合成的 WRF 格式文件报 KeyError: 'Time'现象:用 netCDF4 手工创建了一个存 WRF 输出字段的文件,格式看起来和 wrfout 一致,但一调wrf.getvar就报KeyError: 'Time',或者提示找不到合法时间维度。原因:wrf-python 读取时依赖一个可用的 Time 维度。WRF 模式写出的 wrfout 里 Time 是一个无限维(unlimited dimension),时间变量会随写入时次增长。手工用 netCDF4 创建文件时,如果createDimension漏掉了无限维声明,或者根本没建这个维,解析器就找不到路径。真实 wrfout 文件基本不会触发这个,但做数据合成和测试时会踩。解决:创建文件时显式声明 Time 为无限维:ds.createDimension('Time', None),同时按 WRF 约定的名称写时间变量。如果你只是读取别人给的 wrfout,这个坑可以完全绕开。如果你在写一个给测试用的精简 WRF 文件,记得把时间维度、时间变量、以及 XLAT / XLONG 坐标变量全带上,缺一个都会在 getvar 阶段报出莫名其妙的错误。4.4 import wrf 时进程直接段错误(Segmentation Fault)现象:辛辛苦苦装好 wrf-python,python -c "import wrf"一执行,终端直接报Segmentation Fault,进程退出,没有任何 Python 异常信息。这种问题最吓人,因为它不给你一个明确的堆栈。原因:这是典型的 netCDF4 与底层 HDF5 二进制库不匹配。netCDF4 是用 pip 装的,而 hdf5 或 netcdf 库是 conda 装的,两边 ABI 不一致,import 阶段加载到冲突的共享库,直接崩溃。这类问题跟 wrf-python 本身没什么关系,是环境混用导致的底层链接冲突,属于那种查了半天最后只能靠统一来源解决的“玄学”问题。解决:把 netCDF4 和 HDF5 全部统一到同一来源。我一般是在wrf环境里执行conda install -c conda-forge netCDF4 hdf5 -y,让 conda 重新按兼容版本配对,装完再 import 就正常了。这条打败了不少人的原则请记住:气象库的底层二进制依赖,要么全用 conda,要么全用 pip,尽量不要混着来。4.5 画出来风场方向不对,气压值大了一个量级现象:从 wrfout 里直接读 U、V 变量画地面风场,箭头方向跟再分析资料对比是歪的;自己用原始变量读气压再换算,画出来的海平面气压值比实况大了近十倍。原因:WRF 输出里的 U/V 是格点风(沿网格方向),不是地球坐标下的风;而气压变量在不同输出配置里可能以 Pa 或者 hPa 存储,直接当 hPa 用就放大十倍。这些物理量转换逻辑都内置于 wrf-python 的 getvar 里,绕开它就要自己写换算公式。解决:风场一律用uvmet10或uvmet,它们是旋转后的地球坐标风;气压用slp,不要自己拿 P 变量换算。画地面图时,用uvmet = wrf.getvar(ds, 'uvmet10', timeidx=0),然后取分量u = uvmet[0]、v = uvmet[1],再和经纬度一起喂给绘图函数。若确实需要原始变量做别的事,先确认units属性再动手换算。5. 进阶技巧:把 WRF 网格坐标换算成经纬度并叠加地图验证5.1 用 xy_to_ll 和 ll_to_xy 做单点换算日常后处理经常要回答“某个格点在哪”或“这个经纬度对应第几个格点”这类问题。wrf-python 提供了两个对称的函数,不用自己手写投影反算,直接调库就行:import wrf # 取一个带投影坐标的场做基准 slp = wrf.getvar(ds, 'slp', timeidx=0) # 格点坐标 (x=100, y=60) 换算经纬度 lat, lon = wrf.xy_to_ll(slp, 100, 60) # 反过来:找 30N, 120E 落在哪个格点 x, y = wrf.ll_to_xy(slp, 30, 120) print(lat, lon) print(x, y)参数说明:xy_to_ll第一个参数是任意一个带投影坐标的 wrf 对象,后面是 x 和 y 的格点序号,返回的是该点的纬度和经度;ll_to_xy反过来,参数顺序是(field, latitude, longitude)。注意ll_to_xy返回的格点坐标是浮点数,需要做数组索引时先转成 int 再使用。5.2 用 cartopy 把结果叠到地图上验证最后一步是验证。我习惯把诊断变量和真实地图叠在一起,确认空间位置和量级是合理的。下面是一个最小画图脚本,直接可以跑:import matplotlib.pyplot as plt import cartopy.crs as ccrs import cartopy.feature as cfeature slp = wrf.getvar(ds, 'slp', timeidx=0) lats, lons = wrf.latlon_coords(slp) ax = plt.axes(projection=ccrs.PlateCarree()) ax.add_feature(cfeature.COASTLINE, linewidth=0.6) ax.contourf(lons, lats, slp, transform=ccrs.PlateCarree(), levels=20) plt.show()latlon_coords返回与 slp 网格一一对应的二维纬度和经度数组,直接喂给 cartopy 的contourf,transform用PlateCarree就足够。如果你处理的是高纬度区域或者极地投影模拟,再把投影换成 LambertConformal 或 Stereographic,调用方式不用变。画完之后顺手对比几个特征点的数值,确认量级符合常识,这一步能拦住绝大多数换单位、维序错乱的问题。最后说一个我个人习惯:每次拿到一个新的 WRF 输出文件,第一件事不是画图,而是打印维度、变量 units、缺测值,再把 raw 变量和 getvar 结果做一次对比,确认没有单位或方向问题才开始正式处理。这个动作看起来费时间,实际能省掉画完图才发现数据不对的大返工。wrf-python 1.1.3 版本不算新,但胜在稳定,把上面这些坑绕过去之后,处理 WRF 后处理的效率会提上一个台阶。希望帮到你。本文还有配套的精品资源,点击获取
简介:这是一份面向气象研究与数值模式应用者的Python库资源,即wrf-python 1.1.3官方发行版。该库用于读取、诊断和可视化WRF模式输出,支持Python 3环境下的风场、温度、降水等常见变量计算与制图,适合科研人员及研究生在模式后处理场景中直接部署使用。资源包共328个文件,整体约1.3MB,核心以Python源码和Fortran程序为主,同时包含rst文档、辅助脚本、配置文件及测试数据等,便于用户了解库结构、检查构建参数并完成本地安装。该版本适配常见Python环境,安装配置相对简洁。目前已有2408人学习下载,属于较为常用的小型库包;获取后可在离线环境快速配置依赖,省去自行编译与查找历史版本的时间,尤其适合需要复现论文实验或搭建气象数据批处理流程的开发场景。1. wrf-python 是什么:把 WRF 后处理从手写循环里解放出来WRF 模型的输出文件,几乎每个做过气象数值模拟的人都被它折磨过:几千个变量、坐标混乱、动不动就三四百 MB 的 NetCDF。wrf-python 这个库就是为了把这种折磨降到最低——它把过去 NCL 里那套现成的气象诊断函数(算露点、算海平面气压、算雷达反射率)原样搬进了 Python,用 getvar 一行就能拿到变量,大数组计算全程走 numpy,不用手写循环。下面围绕 wrf-python 1.1.3 这个版本,把从安装、读数据、算诊断变量到坐标换算的完整路径讲清楚。适合三类人:跑 WRF 模式的人、做气象数据后处理的人,以及刚开始用 Python 替代 NCL 的学生和工程师。2. 安装 wrf-python 1.1.3:依赖顺序、环境隔离和 tar.gz 的三种装法安装这一关过不去,后面全都白搭。wrf-python 不是纯 Python 包装的库,它的核心计算代码是 Fortran 编译出来的扩展模块,pip 在装的时候要现场编译,所以环境对不对、编译器有没有,直接决定你接下来是顺利 import 还是面对一屏报错。这一章我把最稳的安装路径拆开讲,从建环境到验证一次性走通。2.1 先建一个独立环境,别往 base 里塞很多人拿到 tar.gz 直接 pip install 到默认环境,结果过几天装了个深度学习框架,numpy 被降级,wrf-python 突然开始报版本冲突。wrf-python 对 numpy、scipy 的版本是敏感的,所以我一般建议项目开始时就用 conda 单独建一个环境,后面重装、换版本都不用担心影响其他项目。顺手把 python 版本选在 3.9 或 3.10 这类比较稳的版本区间。# 创建独立环境并激活 conda create -n wrf python=3.9 -y conda activate wrf参数说明:-n wrf给环境起名叫 wrf,可以换成你喜欢的项目名;python=3.9指定解释器版本,建议别一上来追最新版,部分编译型科学计算库在新版本 Python 刚发布时还没有预编译轮子,现场编译会给你多添一堆麻烦。激活之后命令行会出现(wrf)前缀,后面所有安装操作都锁在这个环境里。为什么强调隔离?因为 wrf-python 装的是带 Fortran 扩展的包,重装一次等于重新编译一次,编译要花几分钟到十几分钟;如果环境干净,一次装对,后面不用反复折腾。我见过有人在 base 环境里反复翻车之后,干脆把所有气象库全装进独立 conda 环境里用,反而再没出过兼容问题。另外,如果你后处理时还要装 cartopy、xarray 这些库,也建议都在同一个环境下解决,它们对 numpy 的版本要求往往互相拉扯,环境隔离是唯一的后悔药。2.2 三种方式把 tar.gz 装上拿到 wrf-python-1.1.3.tar.gz 之后,最常见做法是直接交给 pip 处理。它会把包解压、跑 setup.py、编译扩展模块,再装进当前环境。命令就一行:# 在 tar.gz 所在目录下执行 conda activate wrf pip install ./wrf-python-1.1.3.tar.gz这里的.前缀是告诉 pip 从本地文件安装,不是从公开包索引拉取。pip 会自动解析依赖,numpy、scipy、matplotlib、netCDF4 这些如果环境里没有,它会顺带安装。不过我建议先把依赖用 conda 装好再装这个库,因为 conda 处理 netCDF4 和底层 HDF5 的二进制兼容性比 pip 稳得多,这一点在第 4 章避坑部分会展开讲。第二种方式是复古的源码安装:解压后直接跑 setup.py。这条路径适合你想在安装前改编译参数,或者 pip 处理 source 包出问题的时候用来定位原因:# 方式二:解压后手动 setup 安装 tar -xzf wrf-python-1.1.3.tar.gz cd wrf-python-1.1.3 python setup.py install第三种方式是 pip 直接从公开包索引安装指定版本,不需要本地包文件。适合你只是想要这个版本、不需要改任何代码的场景:# 方式三:从索引直接拉取指定版本 pip install wrf-python==1.1.3三种方式最终装出来的代码是一样的,区别在于包从哪来、构建过程你可控到什么程度。第一次装建议用本地 tar.gz 的方式,因为包文件就在手边,构建失败能直接看到是哪个环节出错,也方便反复重试。在内外网隔离的服务器或者内网集群上,本地 tar.gz 几乎是唯一可靠的路径:在外网机器上提前把包下载好,再传进内网用pip install ./wrf-python-1.1.3.tar.gz装,完全不依赖运行时网络。无论哪种方式,Linux 上都要有 gfortran,macOS 上要有基于 gcc 的 Fortran 编译器。装编译器的命令在这里,Windows 用户建议直接换 WSL 环境来做,省得跟 MSVC 较劲:# Debian / Ubuntu 系 sudo apt install gfortran # macOS(需先有 Homebrew) brew install gccgfortran 就是用来编译 wrf-python 里 Fortran 源文件的,装好之后可以用gfortran --version验证。没有编译器时,pip 一般在构建阶段直接报gfortran: command not found或者类似错误,很多人误以为包坏了,其实只是编译器没装,装完重新 pip install 一次就好。2.3 安装完的快速自检装完别急着跑业务脚本,先做 30 秒自检:确认 import 成功、版本正确。执行下面这条命令:python -c "import wrf; print(wrf.__version__)"正常会打印出类似1.1.3的版本号。如果 import 报错,把报错信息里提到的缺库逐个补上,再重新 import。接下来用一个真实的 WRF 输出文件做最小读取测试,确保 getvar 能正常拿到变量:import netCDF4 as nc import wrf ds = nc.Dataset('wrfout_d01_2023-07-01_00:00:00') slp = wrf.getvar(ds, 'slp', timeidx=0) print(slp.shape, slp.units)wrf.getvar第一个参数是打开的 Dataset 对象,第二个是变量名缩写,timeidx=0表示取第一个时次。返回的 slp 对象自带单位、坐标这些元数据,直接 print 就能看到关键信息。如果能打印出类似(97, 145)和hPa,说明安装和基本调用都过了关,下一步就可以去算正经变量了。3. 上手核心操作:用 getvar 读 WRF 输出并算诊断变量装好之后,真正值钱的部分就是把工作流跑起来。WRF 输出文件里变量很多,但日常后处理真正高频用到的核心操作其实就三类:读变量、算诊断量、做层次插值。这一章按这个顺序给你一套可以照着改的小作业。把下面代码里的文件名换掉,基本就能直接跑出结果。3.1 读文件之前先看结构,别当黑匣子很多人打开 wrfout 文件就直接ds.variables['T'][:]一把梭,结果后面画图时坐标对不上。WRF 输出的网格是 Arakawa-C 格点,不同变量定义在格点上,而且文件里的维度一般是(Time, south_north, west_east),跟常见的(lat, lon)习惯不完全一样。所以我拿到文件第一件事是打印维度和形状,把坐标变量名记下来。import netCDF4 as nc ds = nc.Dataset('wrfout_d01_2023-07-01_00:00:00') print(ds.dimensions.keys()) print(ds.variables['T'].shape) print(ds.variables['T'].dims) print(ds.variables['XLAT'][0, 0, 0], ds.variables['XLONG'][0, 0, 0])ds.dimensions.keys()告诉你文件里有几个维,通常是 Time、south_north、west_east,如果模拟开了土壤方案,还会有 soil_levels 之类的竖向维。T 的 shape 里第一个轴是时次,后面两个是空间维。XLAT 和 XLONG 是每个格点的经纬度,维度里通常带 Time 轴,[0, 0, 0]是第一个时次、第一个格点的经纬度。先确认这些,后续所有操作都不容易跑偏。为什么推荐 getvar 而不是直接读原始变量:WRF 输出里部分变量是压缩存储或者带缺测标记的,直接ds.variables[...]读出来可能带着原始单位,比如位温没做数值转换,风场没旋转回地球坐标。getvar 会在读出来的同时补上单位换算、缺测值处理,还自动带上坐标信息。这就是它存在的意义。对新手来说,判断一个变量该不该用 getvar,一个简单标准是:你打算画图或者做物理量诊断,就一律走 getvar;只是读数据做切片、算均值,可以直接读 raw 变量。3.2 getvar 一行拿诊断变量:slp、td、uvmet10、dbzwrf-python 把气象分析里最常用的一批物理量封装成了“快捷方式”,用缩略名就能直接取。下表是几个我用的最频繁的:变量名物理含义典型用途slp海平面气压地面天气图分析td露点温度湿度分析、对流潜势判断uvmet1010 米风,已旋转到地图投影地面风场图dbz雷达反射率模拟回波与实况对比theta位温层结分析geop位势高度高空形势分析对应代码很简洁:import netCDF4 as nc import wrf ds = nc.Dataset('wrfout_d01_2023-07-01_00:00:00') # 取第一个时次的海平面气压 slp = wrf.getvar(ds, 'slp', timeidx=0) # 取最后一个时次的雷达反射率,timeidx 用 -1 dbz = wrf.getvar(ds, 'dbz', timeidx=-1) # 取10米风,返回的是 u、v 分量组成的风对象 uvmet10 = wrf.getvar(ds, 'uvmet10', timeidx=0) print(slp.shape, slp.units) print(dbz.shape, dbz.units) print(uvmet10.shape, uvmet10.units)参数说明:timeidx是时次索引,0 是第一个、-1 是最后一个;如果传None会返回全部时次的数组,但内存占用明显上去,几十个时次的 WRF 输出文件建议按需取。uvmet10返回的是已经旋转到地图投影的风分量,不是格点坐标下的原始 U/V;想单独拿 u 或 v,可以取返回对象的第一维:u10 = uvmet10[0],v10 = uvmet10[1]。这些返回对象是 xarray DataArray(如果环境里装了 xarray)或 wrf 自带的扩展数组,都带units、coordinates属性。你也可以用wrf.to_np把它转成 numpy ndarray 去配合其他库计算。注意:转 numpy 会丢掉单位信息和坐标,所以画图用原对象,做算术运算用 numpy,这是常见的分工方式。3.3 把模式层数据插值到等压面WRF 模式输出用的是地形追随坐标,物理层高度随地形起伏。做天气分析时,通常要把要素插值到 850 hPa、500 hPa 这些固定等压面上。wrf-python 的interplevel就是干这个的:# 先取气压场和温度场(模式层) pressure = wrf.getvar(ds, 'pressure', timeidx=0) tk = wrf.getvar(ds, 'tk', timeidx=0) # 插值到 850 hPa(pressure 默认单位是 Pa,850 hPa 写 85000) temp850 = wrf.interplevel(tk, pressure, 85000) print(temp850.shape, temp850.units)注意:interplevel的目标层次单位要和气压场一致。wrf.getvar(ds, 'pressure', timeidx=0)返回的 pressure 单位是 Pa,所以 850 hPa 要写 85000。如果你在 getvar 时传了vert_units='hPa',那么 pressure 字段就会变成 hPa,interplevel 里传 850 就可以了。写错单位不会报错,但插值结果会整体偏移,画出来的图看着没啥大问题,数值全是错的,属于典型的“数据正常但不物理”的坑。如果你需要一次性算多个层次,或者需要同时插值温度和相对湿度,可以改用vinterp。vinterp的用法更像“垂直再分析”:给一批层次,按气压或者高度批量插值。常见做法是先把层次列表定好,再循环调interplevel,或者直接上vinterp一次处理完。前者逻辑简单、单层出错好查,后者性能更好。我一般数据量小用interplevel,几十个时次以上用vinterp批量处理。4. 五个高频坑:从安装报错到数据读取翻车排查下面这五个坑,是我和身边几个做模拟后处理的人在不同项目里真实踩过的,覆盖安装和数据读取两条主线。每个都按“现象、原因、解决”拆开,你对照自己的报错就能定位。有些问题看起来像是库里写错了,实际上多半是环境或者单位没有对齐。4.1 pip 安装报 gfortran: command not found现象:pip install ./wrf-python-1.1.3.tar.gz执行到一半,控制台刷出一堆编译日志,最后抛出一个找不到 gfortran 的错误,构建失败。原因:wrf-python 的扩展模块是 Fortran 写的,pip 安装时调用本机编译器现场编译。机器上没有安装 Fortran 编译器,或者编译器不在 PATH 里,就会卡在这一步。这不代表包坏了,只是构建环境缺件。解决:先确认编译器有没有,再重装。Ubuntu/Debian 执行sudo apt install gfortran,macOS 执行brew install gcc。装完用gfortran --version验证版本输出。如果是在内网离线环境,提前把 gfortran 的安装包准备好,再走本地 tar.gz 安装流程。装完编译器之后,直接重跑刚才的 pip install 就行,不需要删除什么残留文件。4.2 getvar 返回数组的维度顺序和文件对不上现象:用 getvar 拿 slp,打印 shape 是(145, 97),但直读ds.variables['SLP']的 shape 是(1, 97, 145)。画图时经纬度对不上,地图上出现一个躺倒的天气系统。原因:wrf-python 内部做了维序重组。getvar 默认吃掉timeidx指定的单时次,把 Time 维压缩掉;另外 uvmet 家族返回的数组第一轴是风的分量(u、v),不是时次。直接拿原始文件的维度顺序去套返回值,空间维就反了。解决:不要用猜的。对返回对象打印shape、units、dims,确认顺序后再喂给画图函数。需要做数组运算时,用wrf.to_np转成 numpy 后特别留意维序,必要时用numpy.transpose调整。养成先看 shape 再动手的习惯,能省掉大量返工。我自己的习惯是每个新变量第一次取出来时,都把它和 raw 变量的维度对照打印一遍,后面就不会再犯。4.3 自己合成的 WRF 格式文件报 KeyError: 'Time'现象:用 netCDF4 手工创建了一个存 WRF 输出字段的文件,格式看起来和 wrfout 一致,但一调wrf.getvar就报KeyError: 'Time',或者提示找不到合法时间维度。原因:wrf-python 读取时依赖一个可用的 Time 维度。WRF 模式写出的 wrfout 里 Time 是一个无限维(unlimited dimension),时间变量会随写入时次增长。手工用 netCDF4 创建文件时,如果createDimension漏掉了无限维声明,或者根本没建这个维,解析器就找不到路径。真实 wrfout 文件基本不会触发这个,但做数据合成和测试时会踩。解决:创建文件时显式声明 Time 为无限维:ds.createDimension('Time', None),同时按 WRF 约定的名称写时间变量。如果你只是读取别人给的 wrfout,这个坑可以完全绕开。如果你在写一个给测试用的精简 WRF 文件,记得把时间维度、时间变量、以及 XLAT / XLONG 坐标变量全带上,缺一个都会在 getvar 阶段报出莫名其妙的错误。4.4 import wrf 时进程直接段错误(Segmentation Fault)现象:辛辛苦苦装好 wrf-python,python -c "import wrf"一执行,终端直接报Segmentation Fault,进程退出,没有任何 Python 异常信息。这种问题最吓人,因为它不给你一个明确的堆栈。原因:这是典型的 netCDF4 与底层 HDF5 二进制库不匹配。netCDF4 是用 pip 装的,而 hdf5 或 netcdf 库是 conda 装的,两边 ABI 不一致,import 阶段加载到冲突的共享库,直接崩溃。这类问题跟 wrf-python 本身没什么关系,是环境混用导致的底层链接冲突,属于那种查了半天最后只能靠统一来源解决的“玄学”问题。解决:把 netCDF4 和 HDF5 全部统一到同一来源。我一般是在wrf环境里执行conda install -c conda-forge netCDF4 hdf5 -y,让 conda 重新按兼容版本配对,装完再 import 就正常了。这条打败了不少人的原则请记住:气象库的底层二进制依赖,要么全用 conda,要么全用 pip,尽量不要混着来。4.5 画出来风场方向不对,气压值大了一个量级现象:从 wrfout 里直接读 U、V 变量画地面风场,箭头方向跟再分析资料对比是歪的;自己用原始变量读气压再换算,画出来的海平面气压值比实况大了近十倍。原因:WRF 输出里的 U/V 是格点风(沿网格方向),不是地球坐标下的风;而气压变量在不同输出配置里可能以 Pa 或者 hPa 存储,直接当 hPa 用就放大十倍。这些物理量转换逻辑都内置于 wrf-python 的 getvar 里,绕开它就要自己写换算公式。解决:风场一律用uvmet10或uvmet,它们是旋转后的地球坐标风;气压用slp,不要自己拿 P 变量换算。画地面图时,用uvmet = wrf.getvar(ds, 'uvmet10', timeidx=0),然后取分量u = uvmet[0]、v = uvmet[1],再和经纬度一起喂给绘图函数。若确实需要原始变量做别的事,先确认units属性再动手换算。5. 进阶技巧:把 WRF 网格坐标换算成经纬度并叠加地图验证5.1 用 xy_to_ll 和 ll_to_xy 做单点换算日常后处理经常要回答“某个格点在哪”或“这个经纬度对应第几个格点”这类问题。wrf-python 提供了两个对称的函数,不用自己手写投影反算,直接调库就行:import wrf # 取一个带投影坐标的场做基准 slp = wrf.getvar(ds, 'slp', timeidx=0) # 格点坐标 (x=100, y=60) 换算经纬度 lat, lon = wrf.xy_to_ll(slp, 100, 60) # 反过来:找 30N, 120E 落在哪个格点 x, y = wrf.ll_to_xy(slp, 30, 120) print(lat, lon) print(x, y)参数说明:xy_to_ll第一个参数是任意一个带投影坐标的 wrf 对象,后面是 x 和 y 的格点序号,返回的是该点的纬度和经度;ll_to_xy反过来,参数顺序是(field, latitude, longitude)。注意ll_to_xy返回的格点坐标是浮点数,需要做数组索引时先转成 int 再使用。5.2 用 cartopy 把结果叠到地图上验证最后一步是验证。我习惯把诊断变量和真实地图叠在一起,确认空间位置和量级是合理的。下面是一个最小画图脚本,直接可以跑:import matplotlib.pyplot as plt import cartopy.crs as ccrs import cartopy.feature as cfeature slp = wrf.getvar(ds, 'slp', timeidx=0) lats, lons = wrf.latlon_coords(slp) ax = plt.axes(projection=ccrs.PlateCarree()) ax.add_feature(cfeature.COASTLINE, linewidth=0.6) ax.contourf(lons, lats, slp, transform=ccrs.PlateCarree(), levels=20) plt.show()latlon_coords返回与 slp 网格一一对应的二维纬度和经度数组,直接喂给 cartopy 的contourf,transform用PlateCarree就足够。如果你处理的是高纬度区域或者极地投影模拟,再把投影换成 LambertConformal 或 Stereographic,调用方式不用变。画完之后顺手对比几个特征点的数值,确认量级符合常识,这一步能拦住绝大多数换单位、维序错乱的问题。最后说一个我个人习惯:每次拿到一个新的 WRF 输出文件,第一件事不是画图,而是打印维度、变量 units、缺测值,再把 raw 变量和 getvar 结果做一次对比,确认没有单位或方向问题才开始正式处理。这个动作看起来费时间,实际能省掉画完图才发现数据不对的大返工。wrf-python 1.1.3 版本不算新,但胜在稳定,把上面这些坑绕过去之后,处理 WRF 后处理的效率会提上一个台阶。希望帮到你。本文还有配套的精品资源,点击获取