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

使用GDAL为多要素图层添加字段后如何保存编辑内容?

问题描述

我用以下Python代码给Shapefile新增字段并修改字段值:

# -*- coding: utf-8 -*-
import os
from osgeo import gdal
from osgeo import ogr
root_path = "xxxxxxxxxxx" # root path
if __name__=='__main__':    
    gdal.UseExceptions()
    ogr.RegisterAll()
    gdal.SetConfigOption("SHAPE_ENCODING", "UTF-8")
    gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES") 
    oDriver = ogr.GetDriverByName("ESRI Shapefile")
    file_list = os.listdir(root_path)
    for dir in file_list:
        if dir.endswith('.shp'):
            oDS = ogr.Open(root_path+dir, 0)
            lyr = oDS.GetLayer()
            LD = lyr.GetLayerDefn()
            lyr.ResetReading()
            print(LD.GetFieldCount())
            if LD.GetFieldIndex('Item_Code') == -1:
                Field = ogr.FieldDefn('Item_Code', ogr.OFTString)
                Field.SetWidth(15)
                LD.AddFieldDefn(Field)
                print(lyr.schema[13].name)
                for feature in lyr:
                    if dir.split('.')[0].startswith('GBZ'):
                        print(feature.SetField('Item_Code', dir.split('.')[0][:15]))
                    elif dir.split('.')[0].startswith('XM'):
                        print(feature.SetField('Item_Code', dir.split('.')[0][:14]))
                    else:
                        print('error')
                    print("once")
                    print(lyr.SetFeature(feature))
                    print(lyr.SyncToDisk())
            oDS.Destroy()

运行输出为:13, Item_Code, None, once, 6, 0。根据官方文档,错误码6对应OGRERR_FAILURE。脚本执行完后用QGIS查看Shapefile,没有任何修改生效。

执行print(lyr.schema[13].name)时能看到图层结构已更新,但无法保存修改。另外,Layer类的UpdateFeature、UpsertFeature方法无法调用,只能用Update方法,GDAL的ogr.Open()和gdal.OpenEx()相关API文档理解起来也比较困难。

环境信息:

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

问题原因及修复方案

核心问题

  1. 只读模式打开数据源:ogr.Open()第二个参数传0是只读模式,无法写入任何修改,这是保存失败的核心原因。
  2. 字段添加方式错误:直接修改LayerDefn对象不会同步到磁盘,必须调用图层的CreateField()方法。
  3. 路径拼接不规范:用root_path+dir拼接路径易出现分隔符问题,且可能因文件名含特殊字符报错。

修复后代码

# -*- coding: utf-8 -*-
import os
from osgeo import gdal
from osgeo import ogr

root_path = "xxxxxxxxxxx" # 根目录路径

if __name__=='__main__':    
    gdal.UseExceptions()
    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(root_path):
        if filename.endswith('.shp'):
            shp_path = os.path.join(root_path, filename)
            # 以可写模式打开数据源(参数1代表可写)
            oDS = ogr.Open(shp_path, 1)
            if not oDS:
                print(f"无法打开文件: {shp_path}")
                continue
                
            lyr = oDS.GetLayer()
            field_idx = lyr.GetLayerDefn().GetFieldIndex('Item_Code')
            if field_idx == -1:
                # 创建字段并添加到图层
                field_def = ogr.FieldDefn('Item_Code', ogr.OFTString)
                field_def.SetWidth(15)
                if lyr.CreateField(field_def) != 0:
                    print(f"添加字段失败: {shp_path}")
                    oDS.Destroy()
                    continue
                
                shp_name = os.path.splitext(filename)[0]
                # 遍历要素设置字段值
                for feature in lyr:
                    if shp_name.startswith('GBZ'):
                        feature.SetField('Item_Code', shp_name[:15])
                    elif shp_name.startswith('XM'):
                        feature.SetField('Item_Code', shp_name[:14])
                    else:
                        print(f"文件名不符合规则: {filename}")
                        continue
                    # 更新要素到数据源
                    if lyr.SetFeature(feature) != 0:
                        print(f"更新要素FID-{feature.GetFID()}失败")
                # 强制同步修改到磁盘
                lyr.SyncToDisk()
            # 释放数据源资源
            oDS.Destroy()

关键修改说明

  • 可写模式打开:将ogr.Open()的第二个参数改为1,获得写入权限,这是修改生效的前提。
  • 规范添加字段:使用lyr.CreateField()方法添加字段,这是OGR官方推荐的修改图层结构的方式。
  • 路径优化:用os.path.join()拼接路径,适配不同操作系统的路径规则。
  • 错误检查:增加文件打开、字段创建、要素更新的错误判断,便于排查问题。
  • 资源管理:确保所有修改操作完成后再释放数据源,避免未写入磁盘就关闭资源。

内容的提问来源于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 15:27:51