You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用GDAL访问Shapefile时无法正确读取属性表的问题

问题描述

我用以下Python代码读取Shapefile:

import os
from osgeo import gdal
from osgeo import ogr
from osgeo import osr

shp_path = "xxxxxxxx"
if __name__=='__main__':
    ogr.RegisterAll()
    gdal.SetConfigOption("SHAPE_ENCODING", "UTF-8")
    gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES") 
    oDriver = ogr.GetDriverByName("ESRI Shapefile")
    path_list= os.listdir(shp_path)
    for dir in path_list:
        if dir.endswith('.shp'):
            oDS = oDriver.Open(dir, 0)
            iLayerCount = oDS.GetLayerCount()
            out_lyr = oDS.GetLayerByIndex(0)
            print(dir, iLayerCount, out_lyr.schema.len(), out_lyr.schema[0].name)

执行后输出:

"GBZ2012371002CZ.shp",1,1,'Item_Code'

但在QGIS中打开该Shapefile的属性表时,能看到大量字段。我怀疑代码没正确访问Shapefile的真实内容,想搞清楚GDAL Layer和QGIS显示内容的关系。

环境信息:

  • QGIS: 3.26.3
  • Python: 3.7.9(64位)
  • GDAL: 3.0.4

后来发现Item_Code字段是我之前误操作生成的:当时错误地用Driver.CreateDataSource而非Driver.Open加载文件,还通过DataSource.CreateLayer创建图层并添加了这个字段。我现在需要找到正确读取QGIS属性表中真实数据的方法。

另外,当我切换到没有生成过Item_Code字段的文件夹时,代码报错:

'NoneType' object has no attribute 'GetLayerCount'

看起来oDS完全无法访问属性表内容。

解决方案

1. 修复文件路径问题

报错'NoneType' object has no attribute 'GetLayerCount'的核心原因是:os.listdir(shp_path)返回的是文件夹内的文件名,而非完整路径,直接传给oDriver.Open()会导致GDAL找不到文件,返回None。

修改路径拼接逻辑:

for filename in path_list:
    if filename.endswith('.shp'):
        # 拼接完整文件路径
        full_shp_path = os.path.join(shp_path, filename)
        oDS = oDriver.Open(full_shp_path, 0)
        if not oDS:
            print(f"无法打开文件: {full_shp_path}")
            continue
        # 后续读取操作

2. 清理误操作生成的冗余文件

之前用CreateDataSource的误操作会生成额外的Shapefile关联文件(比如冗余的.dbf、.shx),甚至覆盖原始文件,导致GDAL读取到错误图层。需要:

  • 删除误操作生成的冗余文件,保留原始Shapefile的完整文件集(.shp、.shx、.dbf、.prj等缺一不可)
  • 若原始.dbf已被覆盖,需要从备份恢复或重新获取原始Shapefile

3. 正确读取属性字段的完整代码

修复后的可运行代码:

import os
from osgeo import gdal
from osgeo import ogr
from osgeo import osr

shp_path = "你的Shapefile文件夹路径"
if __name__=='__main__':
    ogr.RegisterAll()
    gdal.SetConfigOption("SHAPE_ENCODING", "UTF-8")
    gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES") 
    oDriver = ogr.GetDriverByName("ESRI Shapefile")
    
    for filename in os.listdir(shp_path):
        if filename.endswith('.shp'):
            full_path = os.path.join(shp_path, filename)
            oDS = oDriver.Open(full_path, 0)
            if not oDS:
                print(f"打开失败: {full_path}")
                continue
                
            layer_count = oDS.GetLayerCount()
            print(f"\n文件: {filename}, 图层数: {layer_count}")
            
            # 读取第一个图层的所有属性字段
            layer = oDS.GetLayerByIndex(0)
            if not layer:
                print(f"获取图层失败: {filename}")
                continue
                
            schema = layer.schema
            print(f"字段总数: {schema.len()}")
            print("字段详情:")
            for field in schema:
                print(f"- 字段名: {field.name}, 类型: {field.GetTypeName()}")
                
            oDS.Destroy()

GDAL Layer与QGIS内容的对应关系

QGIS加载Shapefile时,底层也是调用GDAL/OGR库,二者的核心对象完全对应:

  • QGIS中的可视化图层 = GDAL中的ogr.Layer对象
  • QGIS属性表的字段 = GDAL中的ogr.FieldDefn对象
  • 你之前看到的字段不一致,是因为误操作生成的冗余文件被GDAL读取,而非原始Shapefile数据。

内容的提问来源于stack exchange,提问作者Paul

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 12:19:54