Python实战:利用cdsapi高效批量下载ERA5日尺度气象数据

张开发
2026/4/13 18:20:19 15 分钟阅读

分享文章

Python实战:利用cdsapi高效批量下载ERA5日尺度气象数据
1. 为什么需要批量下载ERA5气象数据气象数据是科研和工程应用中不可或缺的基础资料。ERA5作为欧洲中期天气预报中心ECMWF提供的第五代再分析数据集包含了从1940年至今的全球气象要素时间分辨率达到小时级别空间分辨率最高可达0.25°×0.25°。相比之前的ERA-Interim数据集ERA5在数据质量和时空分辨率上都有显著提升。在实际工作中我们经常需要获取长时间序列的气象数据。比如研究气候变化可能需要几十年的日尺度数据如果手动一个个下载不仅效率低下还容易出错。我曾经为了获取10年的日降水量数据手动操作花了整整两天时间还经常因为网络问题导致下载中断。这就是为什么我们需要掌握批量下载技巧。cdsapi是ECMWF提供的官方Python接口通过它可以直接从Copernicus Climate Data StoreCDS获取ERA5数据。最新版的CDS-Beta系统已经原生支持日尺度数据的下载比之前需要自己处理小时数据方便多了。这个工具特别适合需要长期气象数据的气候研究者开发气象相关应用的工程师进行区域环境分析的地理工作者2. 环境配置与基础设置2.1 安装必要的Python库在开始之前我们需要准备好Python环境。推荐使用Anaconda创建独立的虚拟环境conda create -n era5 python3.8 conda activate era5 pip install cdsapi xarray netCDF4cdsapi是与CDS服务交互的核心库xarray和netCDF4则是处理下载数据的利器。我建议同时安装这几个库避免后续处理数据时再折腾环境。2.2 获取CDS API密钥使用cdsapi需要先在CDS官网注册账号并获取API密钥访问CDS官网注册账号登录后进入用户设置页面找到API密钥部分将显示的URL和密钥保存到本地~/.cdsapirc文件中文件内容应该长这样url: https://cds.climate.copernicus.eu/api/v2 key: 123456:abcdefgh-1234-5678-9012-345678901234注意这个密钥相当于你的密码千万不要上传到公开的代码仓库。我习惯把.cdsapirc文件权限设置为600防止其他用户读取。3. 单日数据下载实战3.1 基础下载示例让我们从一个最简单的例子开始 - 下载2001年全年的2米气温日平均数据import cdsapi dataset derived-era5-single-levels-daily-statistics request { product_type: reanalysis, variable: [2m_temperature], year: 2001, month: [01,02,03,04,05,06,07,08,09,10,11,12], day: [f{i:02d} for i in range(1,32)], daily_statistic: daily_mean, time_zone: utc00:00, frequency: 1_hourly } client cdsapi.Client() client.retrieve(dataset, request).download(era5_temp_2001.nc)这段代码有几个关键点需要注意dataset指定了我们要下载的数据集名称variable参数可以同时请求多个气象要素daily_statistic支持多种统计方式如daily_max、daily_min等日期格式必须使用两位数字所以我用了f-string格式化3.2 优化下载参数默认设置下载的是0.25°×0.25°的高分辨率数据但很多时候我们并不需要这么精细的数据。通过调整参数可以显著提高下载速度request { # ...其他参数同上... area: [50, 100, 20, 130], # 北,西,南,东 grid: 1.0/1.0, # 1°×1°分辨率 download_format: nc # 直接下载NetCDF格式 }这里我添加了三个实用参数area限定了下载区域格式为[北纬,西经,南纬,东经]grid降低了空间分辨率download_format指定输出格式实测下来下载中国区域1°分辨率的数据比全球0.25°分辨率快5倍以上文件大小也只有原来的1/16。4. 批量下载技巧与优化4.1 多变量多年份下载当我们需要下载多个变量或多个年份的数据时可以封装一个下载函数def download_era5(variables, years, bboxNone, grid1.0/1.0): client cdsapi.Client() for var in variables: for year in years: request { product_type: reanalysis, variable: [var], year: str(year), month: [f{m:02d} for m in range(1,13)], day: [f{d:02d} for d in range(1,32)], daily_statistic: daily_mean, time_zone: utc00:00, grid: grid, download_format: nc } if bbox: request[area] bbox filename fERA5_{var}_{year}.nc try: client.retrieve(dataset, request, filename) print(f成功下载 {filename}) except Exception as e: print(f下载 {filename} 失败: {str(e)}) # 示例下载2001-2005年的温度和降水数据 download_era5( variables[2m_temperature, total_precipitation], yearsrange(2001, 2006), bbox[50, 100, 20, 130] # 中国区域 )这个函数添加了异常处理避免因为单个文件下载失败导致整个程序中断。我在实际项目中发现CDS服务偶尔会出现临时性错误加入重试机制会更稳妥。4.2 下载进度监控与错误处理大规模下载时了解进度非常重要。CDS提供了一个实用的请求状态页面登录CDS官网点击右上角用户名选择Your requests在这里你可以看到所有提交的请求及其状态。通常请求会经历以下状态queued排队中running处理中completed已完成failed失败对于重要的长期任务我建议定期检查这个页面。如果发现某个请求长时间卡住可以尝试取消后重新提交。5. 数据处理与质量控制5.1 数据读取与初步检查下载完成后我们可以用xarray快速检查数据内容import xarray as xr ds xr.open_dataset(ERA5_2m_temperature_2001.nc) print(ds) # 查看时间维度 print(ds.time) # 查看空间范围 print(ds.latitude.values) print(ds.longitude.values) # 提取某个站点的数据 station_data ds[t2m].sel( latitude39.9, longitude116.4, methodnearest )xarray的sel方法可以方便地提取特定位置的数据。methodnearest表示取最近格点这对气象数据分析非常实用。5.2 常见问题排查在实际使用中可能会遇到一些典型问题数据缺失检查请求的时间范围是否有效某些早期年份可能缺少部分数据数值异常ERA5的温度单位是开尔文需要减去273.15转换为摄氏度空间范围不符确认area参数的顺序是[北,西,南,东]下载超时大区域高分辨率数据可能需要数小时处理建议拆分为多个小请求我曾经遇到过下载的数据全是NaN值的情况后来发现是因为请求了不存在的变量名。建议先在CDS网站上确认变量名称的正确性。6. 高级技巧与性能优化6.1 并行下载加速当需要下载大量数据时串行方式效率太低。我们可以使用Python的multiprocessing实现并行下载from multiprocessing import Pool def download_task(args): year, var args download_era5([var], [year]) if __name__ __main__: tasks [(year, var) for year in range(2001, 2021) for var in [2m_temperature, total_precipitation]] with Pool(4) as p: # 使用4个进程 p.map(download_task, tasks)需要注意的是CDS对并发请求有限制通常不建议超过3-5个并行请求。我一般设置4个进程这样既能提高速度又不会触发服务限制。6.2 数据分块处理对于特别大的数据集可以考虑按时间或空间分块下载# 按季度下载 for year in range(2001, 2006): for quarter in [(1,3), (4,6), (7,9), (10,12)]: request { # ...其他参数... month: [f{m:02d} for m in range(quarter[0], quarter[1]1)], } filename fERA5_{var}_{year}_Q{quarter[0]//31}.nc client.retrieve(dataset, request, filename)这种方法特别适合需要高时空分辨率数据的研究。下载后可以使用xarray的concat或merge功能将分块数据合并。7. 实际应用案例7.1 气候变化趋势分析假设我们要分析中国东部地区近20年的温度变化趋势可以这样处理# 下载数据 download_era5( variables[2m_temperature], yearsrange(2001, 2021), bbox[45, 110, 20, 130], # 中国东部区域 grid0.5/0.5 # 中等分辨率 ) # 计算区域年平均温度 annual_means [] for year in range(2001, 2021): ds xr.open_dataset(fERA5_2m_temperature_{year}.nc) annual_mean ds[t2m].mean(dim(time, latitude, longitude)) - 273.15 annual_means.append(annual_mean.values) # 绘制变化曲线 import matplotlib.pyplot as plt plt.plot(range(2001, 2021), annual_means) plt.xlabel(Year) plt.ylabel(Temperature (°C)) plt.title(Annual Mean Temperature in Eastern China) plt.show()这个例子展示了如何将下载的数据直接用于科研分析。通过调整bbox参数可以轻松研究不同区域的气候特征。7.2 气象数据可视化ERA5数据非常适合制作各种气象图表。下面是一个简单的温度空间分布示例import cartopy.crs as ccrs ds xr.open_dataset(ERA5_2m_temperature_2020.nc) temp ds[t2m].isel(time0) - 273.15 # 取第一个时次并转换单位 fig plt.figure(figsize(10, 6)) ax plt.axes(projectionccrs.PlateCarree()) temp.plot(axax, transformccrs.PlateCarree(), cbar_kwargs{label: Temperature (°C)}) ax.coastlines() ax.set_title(Surface Air Temperature) plt.show()这个可视化使用了cartopy库来处理地图投影。对于更复杂的可视化需求可以考虑使用专业的气象绘图软件如Metview或GrADS。

更多文章