Python无需本地保存直接读取网络GRIB文件的报错求解
无本地存储读取网络GRIB文件解决方案
一、pygrib方案修复
你遇到的No final 7777 in message报错是因为pygrib.fromstring仅支持单条GRIB消息输入,你传入的是包含多消息的完整GRIB文件二进制流,修改方案如下:
- 用
urllib完整读取文件字节到内存 - 用
io.BytesIO将字节包装为类文件对象,直接传入pygrib.open即可
代码示例:
import urllib.request import pygrib from io import BytesIO url = 'https://noaa-gfs-bdp-pds.s3.amazonaws.com/gfs.20210801/12/atmos/gfs.t12z.pgrb2.1p00.f000' req = urllib.request.Request(url, headers={'User-Agent': 'Mozilla/5.0'}) # 完整读取文件到内存字节对象 grib_bytes = urllib.request.urlopen(req, timeout=300).read() # 包装为类文件对象,无需写入本地磁盘 with pygrib.open(BytesIO(grib_bytes)) as grbs: # 正常遍历读取GRIB消息 for grb in grbs: print(grb.name)
二、GDAL方案修复
报错根因说明
- 尝试1的证书吊销报错是Windows平台下GDAL默认使用schannel作为SSL后端,默认开启证书吊销检查导致的访问失败
- 尝试2的
vsis3用法错误,无需添加https://前缀,路径格式应为/vsis3/桶名/对象路径 - 尝试3的SSL握手失败同样是schannel证书检查问题导致的分段请求中断
修复方案1:调整GDAL配置直接用vsicurl访问
from osgeo import gdal # 关闭schannel证书吊销检查,解决Windows下SSL报错 gdal.SetConfigOption('GDAL_HTTP_SSL_REVOCATION_LIST_DISABLE', 'YES') # 可额外增大VSICURL缓存块大小,减少网络请求次数降低握手失败概率 gdal.SetConfigOption('VSICURL_CACHE_BLOCK_SIZE', '1048576') # S3数据源访问(vsicurl路径) url = "/vsicurl/https://noaa-gfs-bdp-pds.s3.amazonaws.com/gfs.20210801/12/atmos/gfs.t12z.pgrb2.1p00.f000" grib_ds = gdal.Open(url) if grib_ds: print(f"波段数:{grib_ds.RasterCount}")
修复方案2:内存中转兜底方案(完全绕开GDAL网络请求逻辑)
如果vsicurl仍有网络兼容问题,可先把文件读到内存,再写入GDAL虚拟内存盘/vsimem,完全不涉及本地磁盘写入:
import urllib.request from osgeo import gdal url = 'https://noaa-gfs-bdp-pds.s3.amazonaws.com/gfs.20210801/12/atmos/gfs.t12z.pgrb2.1p00.f000' req = urllib.request.Request(url, headers={'User-Agent': 'Mozilla/5.0'}) grib_bytes = urllib.request.urlopen(req, timeout=300).read() # 写入GDAL虚拟内存盘 vsimem_path = '/vsimem/temp.grib' gdal.FileFromMemBuffer(vsimem_path, grib_bytes) # 从虚拟内存盘读取 grib_ds = gdal.Open(vsimem_path) if grib_ds: print(f"波段数:{grib_ds.RasterCount}") # 用完释放虚拟内存空间 gdal.Unlink(vsimem_path)
适配性说明
以上两种方案都完全不涉及本地磁盘写入,适配你当前的系统限制,在你提供的依赖版本(GDAL 3.3.1、pygrib 2.1.4、Python 3.8)下可正常运行。
内容的提问来源于stack exchange,提问作者Jeremy
相关产品推荐
相关产品推荐

