使用cartopy的shapereader加载shp文件触发访问违规报错如何解决
问题描述
调用cartopy.io.shapereader.Reader()加载本地shp文件时触发访问违例报错,错误信息如下:
OSError: exception: access violation writing 0x0000000000000000
复现代码:
import cartopy.crs as ccrs import matplotlib.pyplot as plt import matplotlib.colors as cor import numpy as np import cartopy.io.shapereader as sr crs = ccrs.PlateCarree() fig = plt.figure(figsize = (10, 10), dpi = 600) ax1 = plt.subplot(1, 1, 1, projection = crs) geom = sr.Reader(r"D:\CS\Krigin\shp\jiangsu.shp").geometries() ax1.add_geometries(geom, crs)
排查思路
按优先级从高到低排查:
- 代码逻辑问题:
geometries()返回的是懒加载迭代器,实例化的Reader对象没有被变量持有,传入绘图方法时可能被垃圾回收提前释放,导致底层C指针悬空,触发空地址写入错误。 - shp文件完整性问题:shp格式是多文件配套结构,同目录下必须存在同名的
.shp、.shx、.dbf三个核心文件,缺失任意一个都会导致底层解析失败。 - 路径与权限问题:Windows环境下路径包含中文、全角特殊字符,或者文件存放在系统权限管控目录,会导致库无法正常读取附属文件,触发底层报错。
- 依赖版本冲突:cartopy依赖shapely、GEOS、pyproj等C/C++编写的底层库,pip/conda混装、版本不匹配时会出现内存访问冲突。
- shp文件本身异常:shp存在几何损坏、包含三维Z/M维度、坐标系定义异常时,旧版本cartopy的解析逻辑会直接崩溃。
解决方案
按排查顺序对应修复即可:
- 修复代码生命周期问题:持有Reader实例,同时将迭代器转为实体列表再传入绘图方法,避免对象提前回收,修改后代码片段如下:
reader = sr.Reader(r"D:\CS\Krigin\shp\jiangsu.shp") geom = list(reader.geometries()) ax1.add_geometries(geom, crs) - 校验shp文件完整性:确认同目录下三个核心配套文件齐全,将文件移动到纯英文、无特殊字符的短路径下测试,比如
D:\test\jiangsu.shp,排除路径和权限问题。 - 修复依赖冲突:不要混用pip和conda安装地理空间相关库。conda环境直接执行
conda install -c conda-forge cartopy重新安装匹配版本的全套依赖;pip环境先卸载已装的cartopy、shapely、pyproj,再下载对应Python版本的预编译whl包手动安装,避免默认源拉取的包和本地底层库不兼容。 - 修复异常shp文件:用桌面GIS工具打开目标shp,执行几何修复,导出为WGS84坐标系的二维无Z/M维度shp文件后再读取。
- 替代读取方案:如果cartopy自带的读取逻辑始终报错,可以先用geopandas读取shp,再将几何对象转为列表传入绘图方法:
import geopandas as gpd js_gdf = gpd.read_file(r"D:\CS\Krigin\shp\jiangsu.shp") ax1.add_geometries(js_gdf.geometry.tolist(), crs)
内容的提问来源于stack exchange,提问作者吃小饼干的老和尚
相关产品推荐
相关产品推荐

