ArcGIS 10.1 Python 编程秘籍(二):用 arcpy 游标与地理处理构建可复用脚本骨架

发布时间:2026/9/29 21:26:10
ArcGIS 10.1 Python 编程秘籍(二):用 arcpy 游标与地理处理构建可复用脚本骨架 1. ArcGIS 10.1 里游标和地理处理工具到底怎么配合如果你在 ArcGIS 10.1 桌面环境里写过批量改属性的脚本大概率遇到过这种局面一个要素类几百上千条记录手动改字段改到眼花想用 Python 自动化又不知道从哪下手。arcpy 提供了两套核心能力——游标SearchCursor / UpdateCursor / InsertCursor负责逐行读写属性地理处理工具Clip、Buffer、SelectLayerByLocation 等负责空间运算。把这两者串起来就能搭出一个可复用的脚本骨架批量属性更新、要素筛选、结果导出都能覆盖。这篇面向的是已经会打开 ArcMap、知道要素类和字段是什么、但还没把 arcpy 脚本跑顺的人。我会给出一套可以直接复制改路径就能用的骨架包含字段映射配置、游标与地理处理工具的协同写法、运行验证步骤以及几个我实际踩过的坑。另外脚本里如果涉及调用外部 API 做辅助处理比如把处理日志或统计结果推送到统一通道凭证管理可以用 TaoToken 的 Key/API 通道统一收口避免把密钥散落在每个脚本里。ArcGIS 10.1 的 Python 版本是 2.7语法上有些地方和 Python 3 不一样比如 print 是语句不是函数字符串默认是字节串。下面的代码都按 2.7 写你直接粘到 IDLE 里能跑。2. 前置准备环境、工作空间与凭证通道2.1 确认 arcpy 可用与工作空间设置ArcGIS 10.1 安装后自带 Python 2.7 和 arcpy不需要额外 pip 安装。打开 ArcMap 的 Python 窗口或者直接开 IDLE先验证import arcpy print arcpy.GetInstallInfo()[Version]能打印出 10.1 就说明环境没问题。接下来所有脚本都建议在开头统一设置工作空间这样后面引用数据集只用写名字不用每次拼全路径import arcpy arcpy.env.workspace rC:\ArcpyBook\data\CityOfSanAntonio.gdb arcpy.env.overwriteOutput TrueoverwriteOutput True这一行很关键。默认情况下如果输出要素类已存在地理处理工具会直接报错终止。批量脚本反复调试时打开覆盖能省掉大量手动删输出的操作。2.2 用 TaoToken 统一管理脚本调用凭证脚本骨架里如果只有本地地理处理其实不需要任何外部凭证。但实际项目里经常会有这类需求把批量处理的结果统计推送到一个统一接口、调用模型对话做字段语义映射建议、或者把脚本注册到某个调度平台。这些场景下如果每个脚本各自硬编码 Key维护起来很痛苦。TaoToken 的做法是提供一个统一的 Key/API 通道你可以在控制台生成 API Key然后在脚本里通过环境变量或配置文件读取而不是写死在代码里。官网入口是 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content API 基址是 https://taotoken.net/api 。生成 Key 的页面在 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi_keysutm_campaignrewrite 接入文档在 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 。在 ArcGIS 10.1 的 Python 2.7 里读取环境变量import os TAOTOKEN_KEY os.environ.get(TAOTOKEN_API_KEY, ) if not TAOTOKEN_KEY: arcpy.AddWarning(未检测到 TAOTOKEN_API_KEY外部调用将跳过)这样脚本本身不含密钥换机器或换人维护时只需要设置环境变量。如果你只是做纯本地属性更新这一段可以先不接等有外部调用需求再加。3. 可复制配置脚本骨架与字段映射3.1 骨架结构一个可复用的 arcpy 脚本我习惯按这个顺序组织导入 → 环境设置 → 配置区路径、字段映射→ 函数定义 → 主流程 → 异常与消息输出。配置区集中放所有需要改的变量别人拿到脚本只改这一块就能用。# -*- coding: utf-8 -*- import arcpy import os # 配置区 WORKSPACE rC:\ArcpyBook\data\CityOfSanAntonio.gdb INPUT_FC Burglary CLIP_FC rC:\ArcpyBook\Ch6\EdgewoodSD.shp OUTPUT_FC rC:\ArcpyBook\Ch6\ClpBurglary.shp # 字段映射源字段 - 目标字段 FIELD_MAP { SVCAREA: SVCAREA, DOW: DOW, CONFIDENCEVALUE: CONFID_RATING } # 分级规则字段值区间 - 标签 RATING_RULES [ (0, 40, POOR), (41, 60, FAIR), (61, 85, GOOD), (86, 100, EXCELLENT) ] # arcpy.env.workspace WORKSPACE arcpy.env.overwriteOutput True3.2 游标与地理处理工具的协同模式核心思路是地理处理工具负责空间筛选游标负责属性读写。两者通过一个中间要素图层或输出要素类衔接。典型流程是先用 SelectLayerByLocation 或 Clip 缩小范围再用 UpdateCursor 批量改属性。def clip_and_update(input_fc, clip_fc, output_fc, field_map, rules): try: # 第一步地理处理工具做空间裁剪 arcpy.Clip_analysis(input_fc, clip_fc, output_fc) arcpy.AddMessage(裁剪完成: output_fc) # 第二步检查目标字段是否存在不存在则添加 existing [f.name for f in arcpy.ListFields(output_fc)] target_field field_map[CONFIDENCEVALUE] if target_field not in existing: arcpy.AddField_management(output_fc, target_field, TEXT, 10) arcpy.AddMessage(已添加字段: target_field) # 第三步用 UpdateCursor 批量写属性 src_field CONFIDENCEVALUE with arcpy.da.UpdateCursor(output_fc, (src_field, target_field)) as cursor: cnt 0 for row in cursor: val row[0] if val is None: continue for low, high, label in rules: if low val high: row[1] label break cursor.updateRow(row) cnt 1 arcpy.AddMessage(已更新 %d 条记录 % cnt) except Exception as e: arcpy.AddError(处理失败: str(e)) raise这里有几个细节值得说。arcpy.da.UpdateCursor是 10.1 新增的数据访问模块比老版arcpy.UpdateCursor快很多而且支持 with 语句自动释放锁。字段列表用元组传入返回的 row 也是按这个顺序索引。updateRow必须在循环内对每一行调用否则改动不会提交。3.3 字段映射配置的灵活写法如果字段名很多硬编码字典容易漏。可以写一个辅助函数根据源要素类的字段自动生成映射建议def build_field_map(fc, suffix_NEW): fields [f.name for f in arcpy.ListFields(fc) if f.type not in (OID, Geometry)] return dict((f, f suffix) for f in fields)这样批量加后缀字段时不用手写。实际用的时候再按需删掉不需要的项。4. 验证请求与成功结果4.1 运行脚本并检查输出把上面的配置和函数拼成一个完整脚本保存为batch_update.py在 IDLE 里按 F5 运行。如果一切正常Python 窗口会依次输出裁剪完成: C:\ArcpyBook\Ch6\ClpBurglary.shp 已添加字段: CONFID_RATING 已更新 1470 条记录然后在 ArcMap 里把ClpBurglary.shp拖进内容表打开属性表确认CONFID_RATING字段已经按规则填好。这一步是验证游标写入是否生效的关键不要只看脚本没报错就认为成功了。4.2 用 GetCount 做数量校验更严谨的做法是在脚本里加数量校验确认裁剪前后记录数符合预期before int(arcpy.GetCount_management(input_fc).getOutput(0)) after int(arcpy.GetCount_management(output_fc).getOutput(0)) arcpy.AddMessage(裁剪前 %d 条裁剪后 %d 条 % (before, after))如果 after 是 0说明裁剪范围没覆盖到任何要素大概率是坐标系不一致或裁剪面位置不对。4.3 外部调用验证可选如果你的脚本需要调用 TaoToken 的模型对话接口做辅助处理验证方式是用一个最小请求确认通道通import urllib2, json def ping_taotoken(api_key): url https://taotoken.net/api/v1/chat/completions payload json.dumps({ model: claude-sonnet-4-20250514, messages: [{role: user, content: ping}], max_tokens: 10 }) req urllib2.Request(url, payload, { Content-Type: application/json, Authorization: Bearer api_key }) resp urllib2.urlopen(req, timeout30) return json.loads(resp.read())Python 2.7 用的是 urllib2不是 Python 3 的 urllib.request。模型对话的入口在 https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_contentmodel_chatutm_campaignrewrite 你可以在那里先手动测通再写进脚本。如果脚本是长期跑的编码任务或 Agent 流程可以考虑 Coding Plan入口在 https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding_planutm_campaignrewrite 。5. 本篇常见错误排查5.1 RuntimeError: cannot open feature class最常见的原因是工作空间路径写错或者路径里有中文/空格没转义。ArcGIS 10.1 对路径比较敏感建议全部用原始字符串r...并且路径中不要有中文。另外确认arcpy.env.workspace设置的是地理数据库或文件夹而不是某个要素类。5.2 游标报 “The cursor is not editable”UpdateCursor 和 InsertCursor 会对数据加锁。如果 ArcMap 或 ArcCatalog 正打开着同一个要素类脚本会拿不到锁。解决办法是运行脚本前关闭 ArcMap 和 ArcCatalog或者把数据复制一份到临时工作空间再操作。用 with 语句能保证锁在块结束后自动释放比手动 del 更可靠。5.3 字段名大小写与个人地理数据库的方括号文件地理数据库和 shapefile 的字段名用双引号个人地理数据库.mdb用方括号。如果你在查询里写SVCAREA North在 .mdb 上会报错要改成[SVCAREA] North。这个差异在跨数据源复用脚本时特别容易踩。可以用arcpy.AddFieldDelimiters()自动处理field arcpy.AddFieldDelimiters(fc, SVCAREA) qry field North5.4 几何令牌用错导致性能骤降如果你只需要坐标用SHAPEXY不要用SHAPE。后者返回完整几何对象在折线或多边形数据上会慢很多。我实测过一个 2600 条记录的多边形要素类用SHAPE比SHAPEXY慢了将近一倍数据量再大差距会更明显。5.5 编辑会话外修改无法撤销在编辑会话外调用 UpdateCursor 的 updateRow 或 deleteRow改动是立即永久生效的没法撤销。如果脚本逻辑有 bug可能把数据改坏。稳妥做法是先用 CopyFeatures 备份一份或者把游标操作包在 Editor 编辑会话里edit arcpy.da.Editor(WORKSPACE) edit.startEditing(False, True) edit.startOperation() # ... 游标操作 ... edit.stopOperation() edit.stopEditing(True)stopEditing(True)表示保存False表示回滚。6. 把凭证和脚本骨架收口到统一通道脚本骨架搭好之后真正影响长期维护的是凭证散落问题。本地地理处理不需要外部 Key但一旦脚本要调用模型接口做字段语义建议、日志汇总或结果推送每个脚本各自管理 Key 就会变成负担。TaoToken 的 API Keys 页面可以集中生成和轮换 Key接入文档里有 Python 2.7 和 3.x 的调用示例。如果你只是偶尔调用用模型对话页面手动验证就够了如果是长期跑的批量编码或 Agent 流程Coding Plan 更适合。回到脚本本身建议把外部调用的部分封装成独立函数通过环境变量读取 Key主流程里用 try/except 包住调用失败不影响本地地理处理结果。这样即使外部通道临时不可用你的批量属性更新和要素处理照样能跑完。