ArcGIS Pro中可以自定义工具箱,工具箱之中可以自动以Python脚本,但是有部分接口规范需要注意,特此记录。ArcGIS 10.x操作类似,原理相同,但是使用的是Python 2.7版本,很多第三方库都用不了了,并且Python 2的语法我自己也是忘得差不多了,调试时各种不顺,因此建议还是用Pro版本,这样就可以使用Python 3.9或以上版本了,目前最新的是ArcGIS Pro 3.3使用Python 3.11环境。

新建工具

在ArcGIS中,打开Catelog面板,在Toolboxes工具栏点击右键,"New Tool Box(.atbx)",即可新建一个自定义的工具箱,对应在文件系统里面会有一个atbx文件和一个xml文件产生,而不是像gdb格式一样的文件夹。

一个工具箱内可以有多个工具,也可以通过工具集(Toolsets)的方式组织管理,直接右键点击刚刚新建的atbx工具箱,点击New→Toolset可以新建工具集,本文简单起见直接新建Script(脚本)

脚本新建窗口中Name只能填英文,是ArcGIS Pro或其它脚本工具调用的索引符,Label可以是中文,用来显示给用户,方便区分,建议简单填写Description项,简单介绍工具用途,方便以后推广使用。(PS:只给自己用的就没必要做成工具了,直接运行arcpy还更方便)

点击OK新建完成,此后点击该脚本的右键菜单中Properties即可回到此窗口

编写功能代码

ArcGIS Pro支持直接在软件内编辑代码,也支持调用PyCharm等编辑器编辑代码,但是我个人的习惯是先在PyCharm中直接调用arcpy把功能实现后再迁移到ArcGIS Pro内,方便调试。

PyCharm中调用arcpy

PyCharm中新建一个普通的空项目,点击File→Settings→Project→Python interpreter→Add Interpreter

ArcGIS官方建议是在conda中运行,但是我个人比较习惯实用venv,其实也是没问题的,只是运行时会有一个warning而已,目前来看没有因为这个影响功能的实现。所以New一个venv,base interpreter选择ArcGIS Pro安装目录/bin/Python/envs/arcgispro-py3/python.exe,勾选Inherit global site-pakages,以便引入ArcGIS Pro的Python解释器的各种库,包括arcpy,点击OK,环境就配置好了,新建一个Python文件,输入import arcpy看看有没有红色波浪线报错就能验证环境配置是否成功。

关于路径参数

很多时候我们处理的都是gdb形式的数据库,在文件管理器里看到的都是一堆看不懂的gdbtable之类的文件(就像下图这样)

这里特别说明一下,我们不必在意gdb内部在文件系统上的路径名,如需访问gdb内的数据,例如访问D:\原始数据库.gdb内的图斑数据,直接将路径D:\原始数据库.gdb\图斑传入arcpy的函数中就能自动识别,当然了,如果不用arcpy直接用os库来访问那必然是Not Found了

小声吐槽一下:gdb这样的文件结构设计属实抽象,处理起来有点尴尬

功能实现

至此,我们便可以放心地在PyCharm中写bug了,以平滑面为例,我一般的操作流程是:

  1. 在ArcGIS Pro中搜索找到此功能并打开

  2. 点击此功能右上角的帮助图标,跳转到ArcGIS Pro的官方文档库查看该功能的Python代码文档

  3. 参考文档回到PyCharm中写bug

主要原因是ArcGIS Pro的功能实在过于复杂,arcpy也略微抽象,导致我自己无法记住各种要用的功能,IDE(PyCharm)也不能实现自动提示与补全(现在借助Copilot可以一定程度上实现自动补全)

进入帮助文档后下滑就能找到该函数的Python文档

于是,据此,我就来写一写

TuRangTU_Smooth = arcpy.cartography.SmoothPolygon(TuRangTU, "土壤图_平滑", "PAEK", "100 Meters", "FIXED_ENDPOINT",
                                                  "RESOLVE_ERRORS")

最终的示例代码片段如下,请读者自行修改代码内的参数和路径:

import arcpy
if __name__ == '__main__':
    arcpy.env.workspace = r"\工作空间.gdb"  # 设置工作空间,即待会儿结果输出的默认位置
    TuRangTU = r"土壤图" # 要平滑图斑的路径
    arcpy.env.overwriteOutput = True # 设置如有同名文件则覆盖
    TuRangTU_Smooth = arcpy.cartography.SmoothPolygon(TuRangTU, "土壤图_平滑", "PAEK", "100 Meters", "FIXED_ENDPOINT",
                                                      "RESOLVE_ERRORS")

这样就能实现平滑面的功能了,置于arcpy的具体玩法,这里不再展开,详情可参阅ArcGIS Pro官方文档;为实现多个功能连续作业,那就自己叠叠乐了。

此时即可在PyCharm中点击运行或调试把代码跑起来了,去看看默认工作空间里面确实已经生成了"土壤图_平滑"这份数据,证明代码没毛病。

移植到工具箱

工具箱传参实现

工具参数设置

我们此前写的Python代码中是直接指定了“土壤图”数据的路径,但是工具箱中为了适应多种情况,需要传入参数指定该路径,首先我们需要修改脚本工具的属性(右键→属性),在Parameter项中设置所有需要传入的参数,包括以下项目

  • Label:标签,用来显示给用户看的

  • Name:用来索引的,就是在另一个Python脚本里面调用这个脚本时传入参数的名字,但是我们写本脚本时不能直接用名字来索引获取值

  • Data Type:传入参数的类型,这里我们选择“要素类”,有很多类型可选,支持的还是挺丰富的,甚至还可以允许多种类型,允许表格形式或多项值传入,还是很nice的

  • Type:选择此参数是否必填,默认是必填项

  • Direction:设置此参数是输入参数,还是指定输出结果的参数。例如我们的例子中输入参数就是土壤图,输出结果就是平滑后的土壤图,如果需要,我们也可以新建一个输出类型的参数用来让用户指定输出位置

  • Filter:非必填,还可以进一步限制参数类型,例如我们限制输入的要素类型为面要素

  • Default:非必填,默认值,用来调试或演示的时候比较有用

  • 其余项目空着也没事

详情参阅ArcGIS Pro官方文档https://pro.arcgis.com/zh-cn/pro-app/3.0/help/analysis/geoprocessing/basics/create-a-python-script-tool.htm

从参数的设置项来看,自定义程度还是挺高的,玩法挺丰富,后面有机会好好盘一盘它

代码获取参数值

正如ArcGIS给的示例代码中注释所说,可以通过GetParameter或GetParameterAsText获取参数值,至于说这么多种类型的数据是怎么都变成text的,规则是怎样,这就暂时还没搞懂了,至少知道我们的Feature Class参数传进来的是那个要素类的绝对路径字符串

代码中我们需要通过参数的下标(序号)来获取参数值,所以改成下面这样

TuRangTU = arcpy.GetParameterAsText(0)

此外,在ArcGIS Pro中运行不需要再设置工作空间,可以删掉下面这行,ArcGIS默认选择本项目的项目数据库为工作空间

arcpy.env.workspace = r"\工作空间.gdb"  # 设置工作空间,即待会儿结果输出的默认位置

改好后,就可以将代码直接复制到Excecution窗口中,点击OK保存,工具就做好了

运行工具

双击工具,就像平常使用ArcGIS Pro工具一样设置好参数,点击运行,工具就运行起来了

用户交互

运行过程非常漫长(在线@ESRI什么时候能优化一下算法?),我们很多时候还需要实时地向用户反馈当前程序运行状态,可以通过消息或进度条的方式实现,因为本文示例不涉及多步操作,无法做到高细粒度的统计,此处只作记录,不作演示

消息

其实类似于Python中的print函数,实时打印一些信息,arcpy中可以调用

arcpy.AddMessage("正在处理中,请稍候")

调用后ArcGIS中就会像下图这样有提示

并且调用此函数,在PyCharm中运行时控制台也会有输出(虽然说是乱码,改一下编码应该能显示),不再需要另外print

进度条

对于可以进行步骤细粒度统计的操作,可以通过以下方式添加进度条。可以设置消息(第2个参数)、总步数(第3个参数)

arcpy.SetProgressor("step", "正在处理...", 0, total_steps, 1)

随后在每完成一个步骤的时候,调用设置进度条位置,传入当前已完成的步数,ArcGIS会自动计算百分比显示进度条

arcpy.SetProgressorPosition(2)

在所有操作结束后可以重置进度条

arcpy.ResetProgressor()

效果如图所示

但是,由于我们无法获得更高细粒度的统计信息(例如平滑操作平滑了几个图斑了),只知道一个大步骤是否完成,所以给出的进度条往往都是卡在那很久不动,一个步骤完成后又突飞猛进,用户体验属实不太友好。

第三方库

我们写脚本有时候难免需要使用到第三方库,PyCharm中调试时直接安装即可,毕竟是venv或conda的虚拟环境,但是也正因为是虚拟环境,实际移植到ArcGIS Pro中就会缺少相应的库,因为没有实际影响到ArcGIS的Python解释器,所以需要给ArcGIS Pro的Python解释器也安装上相应的库,建议是直接在PyCharm中一次性导出一份requirements.txt

可以有两种方法进行安装

方法一:PyCharm里改——图省事儿

PyCharm里头设置解释器,直接设置为ArcGIS Pro安装目录/bin/Python/envs/arcgispro-py3/python.exe ,不再是虚拟环境,然后使用gui或命令行操作安装相应的库,安装成功后在脚本工具中就能调用了。

十分不推荐直接设置ArcGIS Pro为项目解释器而不构建虚拟环境,很可能会导致ArcGIS Pro出错

方法二:传统命令行

命令行中cd到ArcGIS Pro安装目录\bin\Python\envs\arcgispro-py3\Scripts,运行./pip --version看看pip位置是否正确(默认是系统环境变量里面那个),确认正确后执行安装操作

./pip install -r requirements.txt

同样地,安装完成后在脚本工具中就能调用了。

也是十分不推荐在此环境安装各种杂七杂八乱七八糟的库,建议还是在虚拟环境中调试好确认没问题再进行移植

其它玩法

从刚刚的设置过程中所见到的各种设置项可以看到,还有很多设置项我们完全没碰过,更别提API里面提供的众多特性了,因此还有很多玩法这里不再赘述,只是简单讲清楚做一个基本的Python脚本工具所需要的步骤。