ARTICLE DETAIL

资讯详情

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

用Python下载ERA5再分析数据:从配置到避坑全指南

用Python下载ERA5再分析数据:从配置到避坑全指南 用Python下载ECMWF的ERA-5再分析资料这事儿听起来像个标准流程但实际操作里坑不少。ECMWF提供了CDS API官方也推荐直接用Python的cdsapi库来拉数据可很多新手卡在第一步账号怎么注册、密钥文件放哪、脚本怎么写、参数怎么填更别提下载中间突然断线、服务端排队、返回一堆看不懂的报错。这篇文章就围绕“用Python下载ERA-5”这件事从账号配置到脚本编写再到常见问题的排查完整走一遍流程。不管你是气象专业的学生、搞气候分析的研究人员还是刚接触再分析数据想试试手的编程爱好者都能照着做。1. 项目梳理ERA-5下载这件事到底难在哪1.1 ERA-5与CDS API的基本认知ERA-5是ECMWF发布的第五代全球再分析数据集简单说就是把历史观测数据地面站、探空、卫星等用数据同化技术“塞”进数值模式里生成一套时空连续、物理自洽的格点数据。它覆盖从1940年至今的时间范围水平分辨率是0.25°×0.25°时间分辨率可以到小时级是目前气候和天气研究里用得最多的再分析资料之一。要下载ERA-5ECMWF提供了一套规范的下载接口叫CDS APIClimate Data Store API。你不需要自己写爬虫去抓网页也不需要手动点网页上的“下载”按钮只要用Python写个请求把“要哪个数据集、哪些变量、哪个时间段、哪个区域、什么格式”告诉服务器剩下的排队、切分、生成文件都是ECMWF那边处理。数据准备好之后你再用Python把这文件拉到本地。这个流程听起来很简单但很多人的下载脚本能跑通却下载了错误的数据还有人卡在账号授权上或者下载到一半断线重来。所以这篇博文我不光讲“怎么下载”更会讲清楚每一步为什么这么做以及遇到问题怎么排查。1.2 下载流程拆解整个下载过程可以拆成五步注册CDS账号获取专属的API Key在本地写入配置文件Linux/macOS是~/.cdsapircWindows是C:\Users\你的用户名\.cdsapirc安装cdsapi这个Python库编写并运行下载脚本检查下载结果确认数据完整、变量正确。大部分教程都只讲第4步但实际项目里第2步和第5步才是最容易出问题的环节。前两步没做好脚本写得再漂亮也会报401或403第5步不做你可能下载完才发现年份重复、变量缺了、区域框错了白等几个小时。1.3 先算一笔数据量账动手之前我建议你先估一下自己到底需要多少数据。ERA-5的全球格点数是1440×721约等于103.8万个格点。假设你下载单个变量、单时次的float32数据大概4MB如果下载一天4个时次00/06/12/18时就是16MB一年365天就是接近6GB。如果手里项目要下载20年全球数据那就是上百GB的体量。这个估算很重要它会直接影响你的下载策略。数据量小的时候一个请求搞定没问题数据量大的时候就必须按年份、按变量拆成多个小请求否则服务器端容易超时本地也容易出现断流问题。后面写脚本时会专门讲批量拆分这件事。2. 环境准备账号、密钥与Python环境2.1 注册账号并获取API Key想用CDS API下载ERA-5第一步必须是注册CDS账号。打开CDS官网cds.climate.copernicus.eu点右上角登录用邮箱注册一个账号。注册的时候会要求你阅读并同意数据使用条款这个勾选是必须的不然没法访问下载接口。登录之后进入个人主页找到“API key”相关的入口你会看到一串字符串通常由两部分组成一个数字UID和一串很长的token字符串。这串key就是你的“通行证”会写进本地配置文件里。需要特别提醒这串key等同于账号密码千万不要提交到Git仓库也不要截图发群里。我见过不少人把~/.cdsapirc文件直接推到公开仓库结果账号被ECMWF封禁只能重新申诉。2.2 创建.cdsapirc配置文件在本地创建一个文本文件文件名叫.cdsapirc内容格式如下url: https://cds.climate.copernicus.eu/api key: 123456:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx第一行是固定的API地址不需要改第二行的123456是你的UID冒号后面那一长串是你的API Key。两者之间用英文冒号连接不要有多余的空格。存放位置按系统区分Linux/macOS放在用户主目录即~/.cdsapircWindows放在C:\Users\你的用户名\.cdsapirc。Windows用户要注意如果文件名开头带点资源管理器可能看得不直观你可以用记事本“另存为”文件名手动敲成.cdsapirc保存类型选“所有文件”这样就不会被自动加上.txt后缀。2.3 安装cdsapi并验证环境Python环境的搭建这里不详细展开但有一个建议新建一个独立的虚拟环境别直接装在系统Python里。我用的是conda执行下面命令conda create -n era5 python3.10 -y conda activate era5 pip install cdsapicdsapi依赖requests库pip安装时会自动带上。安装完成后可以执行一条简单命令验证配置是否生效python -c import cdsapi; print(cdsapi.__version__)如果没报错说明库装好了。接着可以做一个“空请求”测试看能不能连上服务器import cdsapi c cdsapi.Client() print(c)如果打印出Client(urlhttps://cds.climate.copernicus.eu/api, ...)说明账号和密钥都通过了。如果这一步报401或403多半是.cdsapirc文件格式错了或者Key复制少了字符。3. 写脚本下载从单变量到批量任务3.1 第一个可用的下载脚本先从一个最简单的例子开始。假设我们想下载2020年1月1日全天的2米温度区域选中国中东部输出格式为NetCDFimport cdsapi c cdsapi.Client() c.retrieve( reanalysis-era5-single-levels, { product_type: reanalysis, variable: 2m_temperature, year: 2020, month: 01, day: 01, time: [00:00, 06:00, 12:00, 18:00], area: [55, 73, 15, 135], format: netcdf }, era5_t2m_20200101.nc )这段代码的核心是retrieve方法它接收三个参数数据集名称、数据请求字典、保存文件路径。数据集名称reanalysis-era5-single-levels代表ERA-5单层数据最常用的还有reanalysis-era5-pressure-levels气压层数据和reanalysis-era5-land陆面数据。area参数的四个值分别是北纬上界、西经左界、南纬下界、东经右界顺序是[North, West, South, East]。我这里填的是[55, 73, 15, 135]对应的就是北纬55°、东经73°、北纬15°、东经135°。注意这里的经度范围在CDS里用-180到180表示东经73°就是73东经135°就是135不用做任何换算。3.2 按区域和时间切片下载上面那个例子里time参数我填了4个时次。ERA-5其实提供逐小时数据你可以把一天24个时次全部下载下来time: [ 00:00, 01:00, 02:00, # ... 一直到 23:00 ]但这会成倍增加数据量而且很多研究其实用不到逐小时数据。比如做日平均温度直接用6小时间隔的4个时次就够了。这里给大家一个经验能少下载就少下载因为CDS服务器的队列是按请求数和数据量来排的请求越重排队越久。我第一次下载时贪心一个请求包含了20个变量、10年逐小时数据结果等了快一个小时才轮到还差点超时。区域也是一样如果只是研究华北平原就没必要下载整个中国区域。区域框得越小服务器生成的NetCDF文件越小下载速度也越快。很多人在这一步没有意识到区域缩小十倍文件大小大概也能缩小十倍。3.3 批量循环下载与断点保护实际项目中经常要下很多年的数据比如1979到2020年按年拆分分别下载。直接在一个请求里塞42年数据大概率会把服务器卡到超时所以更稳妥的方式是循环提交import cdsapi import time import os c cdsapi.Client() years [str(y) for y in range(1979, 2021)] months [f{m:02d} for m in range(1, 13)] for year in years: for month in months: filename fera5_t2m_{year}{month}.nc if os.path.exists(filename): print(f{filename} 已存在跳过) continue try: c.retrieve( reanalysis-era5-single-levels, { product_type: reanalysis, variable: 2m_temperature, year: year, month: month, day: [ 01, 02, 03, # ... 按需列出 ], time: [00:00, 06:00, 12:00, 18:00], area: [55, 73, 15, 135], format: netcdf }, filename ) print(f{filename} 下载完成) time.sleep(1) except Exception as e: print(f{filename} 下载失败: {e}) time.sleep(5)这个脚本有两点值得说明。第一检查文件是否已经存在可以实现“断点保护”。下载过程中如果断网重新跑脚本时会跳过已下载的月份不用从头再来。第二time.sleep(1)是给服务器一个缓冲避免连续快速请求触发限流。不要小看这一秒它能让你的任务稳定很多。不过我一般会再加一个更稳健的处理把请求拆到“年月”的粒度而不是“年”的粒度。因为一个月的单变量区域数据请求很小服务器几乎秒回遇到报错重试的成本也很低。3.4 下载后的快速校验下载完成后不要直接拿去分析先用一个小脚本检查文件完整性。最直接的方法是看文件大小是否符合预期但我更推荐用xarray读一下import xarray as xr ds xr.open_dataset(era5_t2m_202001.nc) print(ds) print(ds[t2m].shape) print(ds[t2m].min().values, ds[t2m].max().values)正常情况下t2m的shape应该包含时间维、纬度维、经度维比如(4, 21, 35)。最小值最大值应该在合理的温度范围内。如果读不到坐标信息或者变量名对不上就要回头检查请求字典里的variable名称是不是拼错了。ERA-5的变量名在官网数据文档里都有比如2m_temperature、mean_sea_level_pressure、total_precipitation复制粘贴是最好的方式手敲容易出错。4. 常见报错与排查技巧4.1 认证类报错最常见的报错是401和403。401通常是.cdsapirc里的Key格式不对比如少了冒号、多了空格或者UID和Key对不上403则可能是账号没有同意最新版数据条款。排查这类问题很简单按下面顺序逐一确认检查配置文件路径是否正确检查Key是否完整复制特别是末尾有没有漏字符登录CDS网站看账号状态是否正常是否弹出过新的服务条款需要你勾选临时写个脚本打印cdsapi.Client()的url和key前缀确认库读到了哪个文件但注意不要打印完整Key。4.2 服务端排队与临时故障运行脚本时cdsapi会打印状态信息比如2024-01-01 10:00:00,123 INFO Request ID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx 2024-01-01 10:00:05,456 INFO Request is queued这个“queued”是正常的说明你的请求已经进入服务器队列只需要等待。如果请求量特别大等待时间可能从几秒到几十分钟不等脚本会一直轮询直到任务完成或失败。如果遇到Server error或者Temporary error多半是ECMWF服务端临时抽风。处理方法就是等几秒重试。我在批量下载时就遇到过每隔几个请求就报一次服务端错误我干脆在循环里加了一个重试机制最多重试3次每次间隔10秒max_retry 3 for attempt in range(max_retry): try: c.retrieve(...) break except Exception as e: if attempt max_retry - 1: raise e time.sleep(10)4.3 网络中断与超时下载大文件时网络中断是最让人崩溃的。如果文件已经下载到一半连接断了本地留下的可能是一个不完整的文件。最简单的办法就是删除这个文件重新跑脚本。因为我的脚本里有“文件已存在则跳过”的判断所以千万不能让不完整的文件保留在原地否则脚本会认为这个文件下载过了然后跳过它。我自己踩过这个坑某次下载一个4GB的NetCDF中途断网文件只下到2.5GB脚本退出。重新跑脚本时文件存在判断让它自动跳过了结果就用了一个截断文件后续分析时数据直接缺了一块。现在我的做法是下载完成后再检查文件大小太小就删掉重下。另外如果用wget这类工具可以考虑加断点续传参数但CDS的临时下载链接有时效性过期之后断点续传也没用所以最可靠的还是重新提交请求。4.4 常见问题速查表问题现象可能原因解决方法401 UnauthorizedKey格式错误或配置文件路径不对重新检查.cdsapirc内容确认放在用户主目录403 Forbidden账号未同意最新条款登录CDS官网重新点击同意条款Bad request 400变量名拼错、参数组合不合理对照官方文档检查变量名、数据集名Request is queued服务器排队正常无需处理等待即可Server error / 5xx服务端临时故障Sleep几秒后重试或稍后再跑下载到一半断流网络波动删掉不完整文件重新跑脚本文件能打开但变量为空变量名错误或区域设置过小用xarray检查坐标范围核对area参数4.5 一些小众但实用的技巧最后分享几个我从实践中总结的小经验网上很多教程不会提。第一个是队列分散。CDS的下载任务一般会有一个同时运行的请求数上限如果你同时提交太多任务后面的会被卡住。更稳的做法是逐个提交每个请求之间留出一定间隔。如果确实想并行也不要超过两三个任务同时进行。第二个是用verbose参数观察请求细节。cdsapi.Client()可以传debugTrue这样会打印出更多请求信息排查问题时很有帮助c cdsapi.Client(debugTrue)第三个是善用result对象。如果你不想让retrieve直接写文件而是想拿到下载链接自己处理可以先获取结果对象再手动下载r c.retrieve(reanalysis-era5-single-levels, {...}) print(r.location) # 打印临时下载链接这个技巧在你需要把文件直接拉取到远程服务器时特别管用也不容易因为脚本中断而丢失下载链接。我个人在实际操作中的体会是ERA-5下载这件事真正决定效率的并不是下载速度而是请求设计和管理策略。先想清楚变量、区域、时间范围把大数据拆成小请求再配合文件存在判断和重试机制整个过程会顺很多。还有一个不常被提到但很实在的点尽量在本地网络比较稳定的时间段运行批量任务比如凌晨不要大白天挂着下载一旦断网又要重来。如果你之后还要对ERA-5做区域平均、时间序列提取或者画图分析欢迎继续交流这些又是另一套经验了。
返回列表