背景与目标ERA5 是由 ECMWF 提供的全球气象再分析数据集包含了丰富的气象变量广泛应用于气候研究、数值模拟和机器学习。由于数据量非常庞大直接下载和处理往往效率低下。Google Cloud Storage (GCS) 提供了 ERA5 的公开数据集用户可以直接在线读取而无需提前下载整包数据。为了在本地进行高效分析我们通常会将这些数据转换为Zarr 格式。Zarr 支持分块存储和并行访问能够显著提升数据处理效率并且方便断点续传和大规模计算。本文的目标是展示如何通过 Python 脚本从 GCS 获取 ERA5 数据并将其转换为本地 Zarr 文件为后续科研和工程应用打下基础。环境准备在开始之前需要准备好以下环境和工具Python 环境推荐 3.9依赖库安装pip install pandas xarray gcsfs numpy psutil rich其中xarray用于处理 NetCDF/Zarr 格式的多维数据。gcsfs用于连接和读取 Google Cloud Storage 上的文件。rich用于在终端显示动态进度表格。psutil用于 CPU 绑定和系统资源管理。本地缓存目录脚本中使用了D:\era5_tmp和D:\era5_block_cache来存放临时文件和缓存数据你可以根据自己的硬盘情况修改路径。配置GCS访问权限ERA5 数据集在 Google Cloud Storage 上是公开的因此我们可以直接使用匿名访问模式读取数据无需额外的认证配置import gcsfs fs gcsfs.GCSFileSystem(tokenanon)如果你需要访问的是私有数据集那么就需要额外配置权限。常见的方式包括使用服务账号密钥文件并在代码中指定路径。设置环境变量如GOOGLE_APPLICATION_CREDENTIALS让程序自动读取认证信息。通过Google Cloud SDK登录并授权。在本文的示例中我们主要使用匿名访问模式来读取 ERA5 的公开数据集这样可以直接运行脚本而不必额外配置权限。从GCS读取数据在脚本中我们使用gcsfs来连接 Google Cloud Storage并通过xarray打开 ERA5 的 NetCDF 文件。这样可以直接在云端读取数据而无需提前下载整包。最简单的示例代码如下import gcsfs, xarray as xr fs gcsfs.GCSFileSystem(tokenanon) with fs.open(gcp-public-data-arco-era5/raw/date-variable-pressure_level/2001/11/07/temperature/500.nc) as f: ds xr.open_dataset(f) print(ds)说明gcsfs.GCSFileSystem(tokenanon)使用匿名模式连接到 Google Cloud Storage 的公开数据集。fs.open(...)指定 ERA5 数据集中的某一天、某个变量这里是温度和某个气压层500hPa。xarray.open_dataset(f)用xarray打开 NetCDF 文件得到一个多维数据集对象。print(ds)打印数据集的基本信息包括维度time、latitude、longitude 等和变量。这个示例展示了最基本的读取流程。在完整脚本中会自动遍历日期范围、多个变量和压力层并裁剪到指定的经纬度区域从而批量获取 ERA5 数据。转换为Zarr格式从 GCS 读取到的 ERA5 数据可以直接保存为 Zarr 文件。Zarr 格式支持分块存储和并行访问非常适合大规模科学计算。最简单的写法如下# 将数据集保存为本地 Zarr 文件 ds.to_zarr(local_output.zarr, modew, consolidatedFalse)说明to_zarr()将xarray.Dataset转换为 Zarr 格式。modew表示写入新文件如果已有文件会覆盖。consolidatedFalse关闭索引合并适合逐步追加数据。在完整脚本中保存过程更进一步每个进程会先将数据写入一个临时 Zarr 文件例如D:\era5_tmp\part_xxxx.zarr。主进程再调用merge_one()将临时文件合并到主 Zarr 文件。这种方式避免了单次写入过大或进程间冲突同时支持断点续传。这种“临时写入 合并”的策略在处理 ERA5 这种大规模数据时非常实用可以显著提升稳定性和效率。验证与优化在数据转换为 Zarr 格式后建议进行验证和优化以确保文件完整性和存储效率。验证完整性可以使用xarray.open_zarr()打开生成的 Zarr 文件检查维度和变量是否正确import xarray as xr ds xr.open_zarr(local_output.zarr, consolidatedFalse) print(ds)如果能正常打印出数据集结构说明文件写入成功。若出现错误脚本会自动删除损坏的文件并重新生成。优化存储效率调整分块大小Zarr 支持分块存储可以根据数据访问模式选择合适的块大小。例如按时间维度分块有利于逐日读取。压缩算法可以通过encoding参数设置压缩方式如zlib或blosc在保证读取速度的同时减少存储空间。并行进程数脚本中的MAX_WORKERS控制并行下载数量过高可能导致内存不足过低则影响效率。批次大小BATCH_SIZE决定每次处理的天数可以根据网络和硬盘性能调整。通过这些方法可以在保证数据完整性的同时进一步提升存储和读取效率。代码示例import gcsfs, xarray as xr, pandas as pd, numpy as np, os, shutil # 基础路径ERA5 数据在 GCS 上的公开存储位置 BASE_PATH gcp-public-data-arco-era5/raw/date-variable-pressure_level # 本地 Zarr 文件保存路径 ZARR_PATH rE:\era5_data.zarr # 读取一天的数据并保存为临时 Zarr 文件 def read_one_day(d): # 使用匿名模式连接 GCS公开数据无需认证 fs gcsfs.GCSFileSystem(tokenanon) # 构造指定日期的文件路径这里以温度 500hPa 为例 path f{BASE_PATH}/{d:%Y/%m/%d}/temperature/500.nc # 打开并读取 NetCDF 文件 with fs.open(path, rb) as f: ds xr.open_dataset(f) # 保存为临时 Zarr 文件避免直接写入主文件 tmp_path fD:\\era5_tmp\\part_{d:%Y%m%d}.zarr ds.to_zarr(tmp_path, modew) return tmp_path # 将临时 Zarr 文件合并到主 Zarr 文件 def merge_one(path): ds xr.open_zarr(path) if os.path.exists(ZARR_PATH): # 如果主文件已存在则追加写入按时间维度 ds.to_zarr(ZARR_PATH, modea, append_dimtime) else: # 如果主文件不存在则新建 ds.to_zarr(ZARR_PATH, modew) ds.close() # 删除临时文件节省空间 shutil.rmtree(path, ignore_errorsTrue) # 示例运行读取 2001-11-07 至 2001-11-10 的数据 dates pd.date_range(2001-11-07, 2001-11-10) for d in dates: tmp read_one_day(d) # 下载并保存临时文件 merge_one(tmp) # 合并到主 Zarr 文件 print(全部完成)常见问题与解决方案在实际运行脚本时可能会遇到以下问题权限错误检查 GCS 配置公开数据需设置tokenanon。如果访问的是私有数据需要配置服务账号或环境变量。内存不足减少并行进程数MAX_WORKERS或缩小批次大小BATCH_SIZE避免一次性加载过多数据。网络中断脚本支持断点续传重新运行即可继续处理未完成的部分。文件损坏如果临时 Zarr 文件损坏脚本会自动删除并重新生成确保最终结果完整。应用场景与扩展这种方法不仅适用于 ERA5 数据还可以推广到其他大规模科学数据集科研气候模拟、天气预测、再分析数据处理。工程AI 模型训练数据准备尤其是需要高维气象数据的场景。扩展同样的逻辑可以应用于其他对象存储系统如AWS S3、Azure Blob Storage只需替换存储接口即可。参考资料ERA5 官方文档https://www.ecmwf.int/en/forecasts/datasets/reanalysis-datasets/era5xarray 文档 https://docs.xarray.dev/en/stable/gcsfs 文档 https://gcsfs.readthedocs.io/en/latest/Zarr 项目 https://zarr.readthedocs.io/en/stable/Google Research ARCO ERA5 仓库 https://github.com/google-research/arco-era5完整代码和最新更新请见我的 GitHub 仓库 https://github.com/Schw11n/era5-gcs-to-zarr-