当前位置:首页>python>Python + ArcGIS 批量建库

Python + ArcGIS 批量建库

  • 2026-09-10 10:41:21
Python + ArcGIS 批量建库

总体思路:让 AI 写代码,我负责踩坑和封装

这次的玩法有点不一样——代码不是我一行行敲的,而是让 DeepSeek 帮我写的。

我先根据《河南省村庄规划数据库标准》,让 DeepSeek 整理出三张配置表:要素数据集、图层、字段。然后告诉它我的需求:用 Python 写个脚本,在 ArcGIS 10.7 里读这三张表,自动建库、建图层、加字段,还要带进度条和错误日志。

AI 吐出来的代码框架挺像回事,但一跑就各种水土不服。于是我的工作变成了:拿 AI 的代码当毛坯房,我来精装修——调试编码问题、修坐标系 bug、加名称清洗、补异常捕获,最后再挂到 ArcToolbox 里封装成标准工具。脚本运行逻辑:

读取 CSV 配置表 → 创建文件地理数据库 → 创建要素数据集 → 创建要素类 → 批量添加字段

添加脚本工具

写好的 .py 文件不能直接双击运行,得挂到 ArcGIS 的工具箱里才能用。这一步本身不复杂,但参数设置错了后面全白搭。我把配置步骤列出来,照着做就行。

1. 新建工具箱打开 ArcMap 或 ArcCatalog,在目录树里找到“我的工具箱”,右键 → 新建 → 工具箱,起个名字,比如“村庄规划工具”。

2. 添加脚本右键刚建好的工具箱 → 添加 → 脚本。弹出向导:

  • 名称:填 村庄规划建库(这就是工具显示的名字)

  • 标签:随便填,用于搜索

  • 描述:写清楚工具干嘛的,可选

  • 脚本文件:点文件夹图标,选你保存的 .py 文件

  • 在进程中运行:不勾选(默认)

3. 设置参数

这一步决定了工具界面长什么样、用户要填哪些东西。按顺序添加 6 个参数:

序号
显示名称
数据类型
说明
0
输出文件夹
文件夹
选 GDB 存放的目录
1
地理数据库名称
字符串
输入名称,不用加 .gdb
2
要素数据集配置表
文件
必填
3
图层配置表
文件
必填
4
字段配置表
文件
必填
5
坐标系
坐标系
用户手动选取

重点说一下 参数属性 的细节:

  • 参数 2、3、4:数据类型选“文件”,这样点浏览按钮时选择 CSV 文件。

  • 参数 5:数据类型选“坐标系”,默认会弹出坐标系选择器。不用填默认值,让用户自己选。

配置完的界面长这样:

4. 运行测试填好参数,点确定。工具开始跑,进度条会显示当前步骤和剩余时间,地理处理窗口里实时输出日志。如果 CSV 配置没问题,很快就能看到数据库生成完毕。

避坑指南

坑 1:脚本一跑就 SyntaxError,连第一行都过不去

现象:工具刚点确定,地理处理窗口直接飙红,报 SyntaxError: EOL while scanning string literal,或者 UnicodeDecodeError。

原因:ArcGIS 10.7 自带的 Python 是 2.7 版本,对中文支持天生残疾。如果你的脚本存成了 UTF-8,但没在文件头声明编码,或者声明了但文件本身带 BOM,Python 解释器会用默认的 ASCII 去读文件,一碰到中文立马歇菜。

解决:我试了好几种组合,最后发现最稳妥的办法是:

  • 用 Windows 记事本打开脚本,另存为 ANSI 编码。

  • 在文件第一行加上 # -*- coding: cp936 -*-。

cp936 就是 Windows 简体中文的代码页,这样 Python 用本地编码读文件,里面的中文注释、中文字符串全都老老实实,再也不报错了。


坑 2:读 Excel 比登天还难,xlrd 和 openpyxl 轮番掉链子

需求:从三张 Excel 表里读配置——要素数据集、图层、字段。

第一次尝试:用 xlrd。安装倒挺顺利,但一读中文路径就报 IOError,说找不到文件。查了半天,原来是 Python 2 里的 xlrd 对 Unicode 路径处理有 bug。换成英文路径能读了,但单元格里的中文又变成乱码。

第二次尝试:用 openpyxl。这个库对 .xlsx 支持好,安装也简单:pip install openpyxl==2.6.4。读取没问题了,但速度有点慢,而且共享给别人,别人还要安装openpyxl库。

终极方案:我一拍大腿,干嘛非得跟 Excel 较劲?用 CSV 不香吗?

CSV 是纯文本,Python 内置 csv 模块零依赖,编码完全可控。只需把 Excel 另存为 UTF-8 编码的 CSV,后续读取没啥问题。

CSV 读取核心代码(解决中文乱码的关键):

with open(csv_path, 'rb') as f:    content = f.read().decode('utf-8')lines = content.splitlines()reader = csv.reader(lines)for row in reader:    decoded_row = [cell.decode('utf-8') for cell in row]

注意:必须先用二进制模式读,整体解码成 Unicode,再用 csv.reader 解析。如果直接传 Unicode 给 csv.reader,Python 2 会再次用 ASCII 编码,照样报错。


坑 3:坐标系参数传进去就报“该值不是空间参考”

现象:工具界面明明选了坐标系(比如 CGCS2000 3 Degree GK Zone 38),运行到创建要素数据集那一步时,ArcGIS 直接甩脸:

ERROR 000840: 该值不是空间参考。

原因:arcpy.GetParameter(5) 返回的可能是字符串(WKT 或名称),也可能是 SpatialReference 对象,但直接传给 CreateFeatureDataset_management 不一定兼容。尤其在 ArcGIS 10.7 里,工具界面的坐标系参数经常返回一个无法直接识别的字符串。

解决:写一个健壮的坐标系解析函数,不管输入什么格式,都强行转成可用的 SpatialReference 对象:

def get_spatial_reference(input_param):    if hasattr(input_param, 'factoryCode'):        return input_param    sr_str = str(input_param)    try:        return arcpy.SpatialReference(int(sr_str))    except: pass    try:        return arcpy.SpatialReference(sr_str)    except: pass    if sr_str.endswith('.prj') and os.path.exists(sr_str):        return arcpy.SpatialReference(sr_str)    sr = arcpy.SpatialReference()    sr.loadFromString(sr_str)    return sr

有了这个函数,无论参数是啥,都能稳稳当当转成坐标系对象,再也没报过 000840。


坑 4:图层名称包含括号、空格,ArcGIS 直接拒绝

现象:CSV 里图层名叫 交通基础设施(点),看起来挺正常,结果创建要素类时 ArcGIS 报错:

ERROR 000354: 名称包含无效的字符

原因:ArcGIS 要素类命名规则非常严格——只能包含字母、数字、下划线,且不能以数字开头。括号、空格、中文横线全都不允许。

解决:写一个名称清洗函数,把非法字符全替换成下划线,如果首字符是数字就加个前缀:

import redef sanitize_name(name):    cleaned = re.sub(ur'[^\u4e00-\u9fa5a-zA-Z0-9_]', u'_', name)    cleaned = re.sub(ur'_+', u'_', cleaned).strip(u'_')    if cleaned and cleaned[0].isdigit():        cleaned = u'F' + cleaned    return cleaned if cleaned else u'FeatureClass'

清洗后 交通基础设施(点) → 交通基础设施_点_。别名(Alias)还是用原来的中文名,既符合规范又不影响可读性。


坑 5:字段长度和精度读出来是文本,添加字段时报错

现象:字段添加时 ArcGIS 报 ERROR 001526: 字段长度无效。

原因:CSV 里字段长度列填的 18,但 csv 读出来全是字符串 '18',而 arcpy.AddField_management 要求整数。

解决:读取时强制类型转换,并加上 try-except 兜底:

length = Noneif row[idx_len]:    try:        length = int(row[idx_len])    except:        arcpy.AddWarning(u"字段长度值无效,将使用默认值")

这样不管用户填的是数字还是文本,都能正确转成整数。


坑 6:进度条一动不动,用户以为工具卡死了

现象:创建大量图层和字段时,工具界面一片空白,进度条纹丝不动,同事跑过来问我:“你这工具是不是挂了?”

解决:用 arcpy.SetProgressor 和 SetProgressorLabel 实时更新状态。每完成一个子任务就调用 SetProgressorPosition(),顺便估算剩余时间:

arcpy.SetProgressor("step", u"正在创建数据库...", 0, total_steps, 1)for i, layer in enumerate(layers):    arcpy.SetProgressorPosition(current_step)    arcpy.SetProgressorLabel(u"正在创建:{0}".format(layer_name))

加上这个之后,用户能清楚看到当前进度和剩余时间,再也没人怀疑工具卡死了。


坑 7:出错后看不到真正原因,日志里只有 ERROR 999999

现象:脚本崩溃只显示 ERROR 999999,完全不知道哪里错了。

解决:在最外层 main() 里用 try-except 包裹,并用 traceback.format_exc() 打印完整堆栈:

except Exception as e:    arcpy.AddError(u"错误信息:{0}".format(safe_unicode(e)))    arcpy.AddError(traceback.format_exc())    raise

这样一来,出错时日志里会清清楚楚显示哪个文件的第几行、什么原因,调试效率直接翻倍。


最终效果:一键生成 10+ 图层的村庄规划空库

经过这七重磨砺,脚本终于稳定下来。看看最终成果:

  • 输入:三个 CSV 配置表 + 在工具界面选一下坐标系

  • 输出:一个文件地理数据库,里面自动建好 3 个要素数据集、10 个要素类(面、线、点),每个要素类自动添加 20~50 个属性字段,字段类型、长度完全符合《数据库标准》。

  • 运行时间:大约 2 -5分钟

工具界面清爽,运行日志详细,即使不懂代码的同事也能根据日志快速排查配置表错误。原本需要半天的手工建库工作,现在一杯咖啡的功夫就搞定了。


我的几点小感悟

  1. Python 2.7 环境下的中文编码:Windows 下用 ANSI + cp936 声明最稳,别死磕 UTF-8。

  2. 数据源能用 CSV 就别碰 Excel:省去第三方库依赖,编码完全可控。

  3. 坐标系参数永远不要直接信任:封装一个万能的解析函数,以不变应万变。

  4. 名称清洗是必备工序:用户输入什么奇葩字符都有可能,自动清洗保平安。

  5. 进度条和日志是工具的脸面:让用户知道工具在干活,出错时能快速定位。

  6. 异常捕获要彻底:用 traceback 打印全堆栈,别让错误信息被吞掉。

最后说一句:工具是给人用的,多花一点时间让界面友好、日志清晰,能省下无数解释的时间。


需要完整脚本的朋友,可以在公众号后台回复「村庄规划建库」,我把 CSV 版脚本和示例配置表打包发给你。

技术之路,踩坑不断,填坑不止。与各位共勉!


📌 今日学习笔记

学到了什么:

  • Python 2.7 中文编码的终极解决方案(ANSI + cp936)

  • CSV 比 Excel 更适合做配置文件

  • ArcPy 坐标系参数的健壮处理方法

  • 要素类命名的清洗技巧

  • 进度条和日志的正确打开方式

  • 如何在 ArcToolbox 中正确配置脚本工具参数

代码对比:

  • 之前:手工建库,半天起步

  • 现在:一键运行,2 分钟搞定

用时:4小时

心情: 看着工具刷刷刷建库,成就感满满


📢 我是老李,35岁规划师,从零开始学AI。

每天1小时,记录真实学习路。不求成为大神,只为多一条出路。

如果你也在传统行业或者对未来感到焦虑,如果你也想学点新东西但一直没有开始

点击关注,我们一起进步;

也欢迎点赞 ❤️ 分享 ➕ 推荐,让更多同行者看到!

👇👇👇

最新文章

随机文章