
简介面向ArcGIS初学者与GIS入门用户这份PDF系统梳理了在ArcGIS中调用Python脚本的方法帮助读者从零掌握用Python完成地理处理、数据转换与模型构建等任务。资源共1个PDF文件压缩包约1.08MB以33页篇幅从Python语言基础讲起涵盖数学运算符、字符串操作、模块导入、函数定义、流程控制及输入输出随后切入arcpy地理处理对象、工具箱与别名调用、ModelBuilder中嵌入脚本、PythonWin调试以及Describe和Exists等常用数据信息获取方式。内容编排清晰既适合完全没接触过编程的GIS用户按章节入门也可供需要系统梳理ArcPy用法的学习者快速查阅。该资源目前已有1001人学习/下载是一份体量精炼但知识点覆盖较完整的ArcGIS Python脚本入门材料。1. 在 ArcGIS 里写 Python 脚本先看清 ArcPy 的边界很多地理信息从业者第一次接触 Python是为了在 ArcGIS 里少重复点鼠标。ArcPy 是 Esri 随桌面软件发布的 Python 地理处理库既能调用 ArcToolbox 里的绝大多数工具也能直接读写要素类、栅格和表格批量裁剪影像、定义投影、字段计算、数据检查都能用几行脚本完成。但 ArcPy 和平时装的 Python 是两回事ArcMap 10.x 内置 Python 2.7ArcGIS Pro 是 Python 3.x环境不对连 import arcpy 都会报错。这篇按解释器选择、工具调用、游标批处理、脚本工具化、性能排错的路径展开新手能跟着跑通老手可以直接取走参数和避坑点。2. 跑通第一个 ArcPy 脚本解释器、窗口与工具箱调用2.1 先定位 ArcGIS 自带的 Python 解释器打开 ArcMap 菜单栏的 Geoprocessing → Python或者 ArcGIS Pro 的“分析”选项卡 → Python会弹出 Python 窗口。这个窗口绑定的是 ArcGIS 自带解释器所有与 arcpy 相关的东西都从这里跑。常见问题是用户安装 Python 3.x 后又照着普通 Python 安装教程配了环境变量接着在 cmd 里执行 python.exe然后在脚本里 import arcpy 时得到 ModuleNotFoundError。arcpy 不会出现在 PyPI 上pip install arcpy 是装不出来的它随着 ArcGIS 安装包一起分发。ArcMap 10.x 与 ArcGIS Pro 的 Python 环境差异先看这张表项目ArcMap 10.xArcGIS ProPython 版本2.73.x常见解释器位置C:\Python27\ArcGIS10.x\python.exeC:\Program Files\ArcGIS\Pro\bin\Python\envs\arcgispro-py3\python.exe桌面端入口Geoprocessing → Python分析选项卡 → Python命令行入口直接运行上方 python.exe运行 propy.bat 或激活 conda 环境在 cmd 里用如下命令验证解释器能否正常导入 arcpyC:\Python27\ArcGIS10.8\python.exe -c import arcpy; print(arcpy.__file__)如果打印出 arcpy 模块所在路径说明解释器可用。如果提示找不到模块或者直接打开的是 Python 3 的解释器先把 PATH 环境变量里其他 Python 临时去掉再试一次。注意ArcGIS Pro 的命令行入口是 propy.bat而不是直接调用 envs 里的 python.exe。propy.bat 会先激活 conda 环境、加载许可直接跑 python.exe 经常连 arcpy 都导不进来。2.2 跑通第一段脚本读取要素类列表把下面代码保存为 list_fc.py用上一步确认的解释器运行。脚本逻辑是做一次数据盘点列出 workspace 里所有面要素类。# -*- coding: utf-8 -*- import os import arcpy arcpy.env.workspace rE:\gis_data for fc in arcpy.ListFeatureClasses(*.shp, Polygon): print(os.path.basename(fc))代码说明# -*- coding: utf-8 -*-是 Python 2 环境的中文编码声明。ArcMap 10.x 的 .py 文件只要有中文字符就必须加否则直接语法报错。env.workspace 指定工作空间这之后凡是写相对路径都会拼到这个目录下相当于 GIS 桌面端里的“当前文件夹”。ListFeatureClasses 返回工作空间内的要素类列表第一个参数*.shp是通配符第二个参数Polygon限定要素类型。要处理点数据把 Polygon 改成 Point要处理线改成 Polyline。工作空间里有多个要素数据集时可以再加第三个参数指定数据集范围。把 print 换成 arcpy.AddMessage这段代码在脚本工具里也能直接复用。2.3 调用工具箱工具工具名_工具箱别名ArcPy 工具函数命名规则是工具名_工具箱别名。缓冲区工具位于 Analysis Tools 工具箱别名 analysis因此函数名写作 Buffer_analysis# -*- coding: utf-8 -*- import arcpy arcpy.env.workspace rE:\gis_data arcpy.env.overwriteOutput True arcpy.Buffer_analysis( in_features地块.shp, out_feature_class地块_缓冲.shp, buffer_distance_or_field5 Meters, dissolve_optionALL )参数说明in_features 是输入要素。脚本独立运行时写相对路径即可因为它会基于 env.workspace 解析在 ArcMap 里直接跑代码时也可以传内容列表里的图层名。buffer_distance_or_field 是缓冲距离必须带单位比如 5 Meters如果是地理坐标系要素要写成 0.5 Degrees。dissolve_option 设为 ALL重叠缓冲区会合并成一个要素设为 NONE每个输入要素都保留自己的输出结果。批处理做简化图形时ALL 能显著减少要素数量。ArcGIS Pro 里也可以写成arcpy.analysis.Buffer(...)模块式写法在智能提示上比下划线版本友好。旧项目里大量_别名写法读别人代码时两种都要认识。2.4 第一次运行报错时按这个顺序检查常见的 ERROR 000732 “Dataset does not exist or is not supported” 多数不是数据真的不存在而是脚本的运行环境和你以为的不一致。按下面顺序排查确认 env.workspace 已设置并且用arcpy.Describe(xx.shp)能读到数据。确认路径用的是绝对路径文件名大小写和扩展名与磁盘一致。检查路径里的反斜杠是否被转义。写字符串路径时加 r 前缀rE:\gis_data是习惯做法不加 r 时\g会被当成转义符路径直接失效。确认没有其他编辑器会话占用了目标要素类。被锁住时脚本写入会报锁错误先保存并关闭编辑会话再跑。用 arcpy.Describe 打印元数据是最快的定位手段desc arcpy.Describe(rE:\gis_data\地块.shp) print(type: {}.format(desc.dataType)) print(sr: {}.format(desc.spatialReference.name))dataType 会告诉你这是一个 FeatureClass、Raster 还是 TablespatialReference.name 能看到坐标系全名。这两项确认无误后续工具调用才谈得上参数对不对。3. 用列表、环境变量和游标做批处理ArcPy 的三种武器3.1 先设好环境变量批处理才不会各跑各的写批处理时最怕每个工具都粘贴一长串绝对路径改一处漏一处。用 env 把“工作位置”固定下来后续脚本会清爽得多。# -*- coding: utf-8 -*- import arcpy arcpy.env.workspace rE:\project\shp arcpy.env.scratchWorkspace rE:\project\scratch arcpy.env.overwriteOutput True arcpy.env.outputCoordinateSystem arcpy.SpatialReference(3857)四个环境变量的作用workspace默认工作空间绝大多数相对路径的基础目录。scratchWorkspace临时数据放置目录。中间结果放这里最后统一清理不污染正式成果。overwriteOutput置 True 后输出文件已存在时直接覆盖。不设置的话第二次运行就会报已存在错误。outputCoordinateSystem新建数据的默认坐标系。工具自带输出坐标系参数时显式指定的优先这个环境变量只是兜底。设置完环境变量用 Describe 检查数据源是否被正确解析避免后续一串工具作用在错误数据上desc arcpy.Describe(地块.shp) print(type: {}.format(desc.dataType)) print(sr: {}.format(desc.spatialReference.name))如果这里读到的坐标系还是旧的说明你调用的工具显式指定了输出坐标系环境变量没有覆盖它。批处理出现“有的输出是 3857有的是别的坐标系”这种情况多半就是工具参数里写死了坐标系要去工具调用处找原因。3.2 三种游标Search 只读、Update 可改、Insert 新增批处理里经常要逐行读属性、改属性或写入新记录。arcpy.da 下的三种游标分工明确游标可写适用场景关键方法SearchCursor否统计、筛选、导出属性for row in cursorUpdateCursor是批量修改属性与几何cursor.updateRow(row)InsertCursor是批量写入新要素cursor.insertRow(row)用 UpdateCursor 把 DLBM 字段中地类码为 01 且面积字段为负的记录修正为 0101import arcpy with arcpy.da.UpdateCursor(地块.shp, [DLBM, TQMJ]) as cursor: for row in cursor: if row[0] 01 and row[1] is not None and row[1] 0: row[0] 0101 cursor.updateRow(row)这段代码的要点fields 参数传[DLBM, TQMJ]row 元组按这个顺序返回字段值row[0] 是地类码row[1] 是面积。updateRow 必须被调用否则循环结束修改不会落盘。判空写在比较前面。ArcGIS 要素类字段允许 NULL直接执行row[1] 0可能抛 TypeError。with 语句退出时自动释放游标不会锁住要素类。不要用旧式arcpy.SearchCursor()且不关闭长时间运行容易积压锁。3.3 ListFeatureClasses把批处理的循环骨架搭起来批处理场景里最典型的循环是遍历要素类 → 拼输出名 → 调用工具 → 输出提示。下面代码把工作空间里所有 Polygon shp 各做一圈 10 米缓冲结果写到 File GDBimport arcpy arcpy.env.workspace rE:\project\shp arcpy.env.overwriteOutput True out_gdb rE:\project\result.gdb for fc in arcpy.ListFeatureClasses(*.shp, Polygon): base arcpy.Describe(fc).baseName out out_gdb \\ base _buf arcpy.Buffer_analysis(fc, out, 10 Meters, dissolve_optionALL) arcpy.AddMessage(done: {}.format(base))逻辑说明Describe(fc).baseName 取去掉路径和扩展名的真正名称否则输出名会带一堆路径前缀。字符串拼接里\\转义出一个反斜杠也可以写成out_gdb os.sep base _buf可读性更好。AddMessage 会把信息送进地理处理消息窗口。print 在独立运行时能看到但在脚本工具里不可见。要处理栅格把 ListFeatureClasses 换成 ListRasters(*.tif)要处理表格用 ListTables。循环体内部换成对应的工具函数批处理骨架不需要变。3.4 统计与分组用 Statistics_analysis而不是自己写循环批量跑完工具常常要按地类统计面积。ArcGIS 自带的统计工具更快还避免手工累加的 NULL 坑arcpy.Statistics_analysis( in_table地块.shp, out_table地块统计.dbf, statistics_fields[[TQMJ, SUM]], case_field[DLBM] )statistics_fields 是二维数组每项[字段名, 统计类型]SUM、MEAN、MAX、MIN 都可以写。要统计多个字段就多放几个列表项。case_field 相当于 GROUP BY可以传多个字段实现多级分组。如果统计结果只在本脚本内部使用不想落磁盘可以用游标累加counts {} with arcpy.da.SearchCursor(地块.shp, [DLBM, TQMJ]) as cursor: for code, area in cursor: counts[code] counts.get(code, 0) (area or 0) for code, total in counts.items(): print({} {}.format(code, total))两点区别要注意Statistics_analysis 输出 dbf 表可以继续接 Table Select 等工具游标结果只活在内存里。统计工具会忽略 None 值手动累加时要用(area or 0)把 None 按 0 处理不上防御整个脚本会报错。4. 把 Python 脚本封装成 ArcGIS 自定义工具参数、消息与异常4.1 用 GetParameterAsText 接收工具箱参数脚本写得再漂亮每次都要改路径就不够“工具化”。把脚本挂到工具箱里参数让用户在界面填是落地到生产环境的关键一步。创建方式在 ArcMap/ArcGIS Pro 的目录窗口中右键目标工具箱 → 添加 → 脚本选择 .py 文件然后进入参数页添加三个参数输入要素设 Input / Feature Layer缓冲距离设 Optional / Double输出要素设 Output / Feature Class。保存后再双击运行时用户只需要浏览图层和填数字。脚本端用 arcpy.GetParameterAsText 按索引读取fc_in arcpy.GetParameterAsText(0) dist_text arcpy.GetParameterAsText(1) fc_out arcpy.GetParameterAsText(2) if dist_text: dist float(dist_text) else: dist 0.0 arcpy.Buffer_analysis(fc_in, fc_out, {} Meters.format(dist))参数说明索引从 0 开始与工具箱参数页的排列顺序一致。GetParameterAsText 永远返回字符串数值参数需要自己转 float。Optional 参数用户没填时返回空字符串直接转 float 会报错要先判空。如果参数设成 MultiValue返回值是分号分隔的字符串处理时先 split 再 striplayers [x.strip() for x in arcpy.GetParameterAsText(0).split(;)]4.2 用 AddMessage 输出进度用户才知道脚本活着脚本工具在桌面端后台运行时用户看不到控制台只能靠地理处理消息获得反馈。三种级别对应不同表现消息函数级别用户看到的表现arcpy.AddMessage信息绿色消息arcpy.AddWarning警告黄色消息不中断arcpy.AddError错误红色错误中断工具统计总数量并按比例输出进度total int(arcpy.GetCount_management(fc_in).getOutput(0)) step max(1, total // 10) for i, (fid,) in enumerate(arcpy.da.SearchCursor(fc_in, [FID]), 1): if i % step 0: arcpy.AddMessage(processed {}/{} {}%.format(i, total, int(i * 100 / total)))代码说明GetCount_management 返回 Result 对象必须 getOutput(0) 再转 int否则拿到的是一串对象描述。//是整除避免 Python 3 里浮点除把 step 变成小数。每处理十分之一才发一条消息。几十万行要素时频繁 AddMessage 会拖慢整体速度这里做了降频。4.3 异常处理分开捕获 ExecuteError 和通用 Exception工具在批量跑数据时任何一步都可能失败。最稳妥的写法是把主体放进 try错误统一写日志import traceback try: arcpy.Buffer_analysis(fc_in, fc_out, 5 Meters) except arcpy.ExecuteError: arcpy.AddError(arcpy.GetMessages(2)) with open(rE:\logs\arcpy_err.log, a, encodingutf-8) as f: f.write(traceback.format_exc() \n) except Exception: with open(rE:\logs\arcpy_err.log, a, encodingutf-8) as f: f.write(traceback.format_exc() \n)要点arcpy.ExecuteError 只接收地理处理框架执行失败的错误Python 语法错误、变量未定义这类异常要靠第二个 except 兜住。arcpy.GetMessages(2) 返回错误级别的所有消息比 str(e) 信息全。写文件用追加模式 “a”覆盖模式 “w” 会把上一次的错误历史清掉排错时无从对比。ArcMap 10.x 的 Python 2.7 中open 不支持 encoding 参数。旧环境兼容写法是把 encoding 去掉并以二进制追加写入with open(rE:\logs\arcpy_err.log, ab) as f: f.write(traceback.format_exc().encode(utf-8, ignore))这样日志以 UTF-8 字节落盘记事本打开不乱码。4.4 命令行调用与计划任务用 propy.bat 而不是裸 python有些脚本不适合面对面跑比如定时任务、服务端自动处理。Windows 命令行直接调 ArcMap 自带解释器C:\Python27\ArcGIS10.8\python.exe E:\scripts\batch_buffer.pyArcGIS Pro 环境用 propy.bat 更稳定C:\Program Files\ArcGIS\Pro\bin\Python\Scripts\propy.bat E:\scripts\batch_buffer.py原因在于 Pro 的 Python 由 conda 管理直接调用 python.exe 时 PYTHONPATH 和许可环境没装配好arcpy 导入常常失败。propy.bat 把这些都处理好了。在 Windows 计划任务里填这个命令时起始位置要写成脚本所在目录不要依赖相对路径。5. 批量字段计算、裁剪影像的性能排错经验5.1 能下推到引擎就不要用 Python 游标逐行跑改字段值常见的错误是一上来就写 UpdateCursor。字段计算器调用的是引擎内部的批量更新速度比游标快一个量级arcpy.CalculateField_management( in_table地块.shp, fieldTQDJ, expressionclassify(!TQMJ!), code_blockdef classify(area): if area 1000: return big if area 100: return mid return small )expression 里!TQMJ!是字段引用语法code_block 定义函数判断条件从大到小写。只改部分记录时传 where_clause例如where_clauseFLAG1更新范围比全表更新小得多。5.2 批量裁剪影像黑边问题与 extent 验证裁剪界面默认按要素外接矩形裁黑边就是这么来的。显式传 clipping_geometry 的写法import arcpy arcpy.env.workspace rE:\clip_shp arcpy.env.compression LZW for shp in arcpy.ListFeatureClasses(范围_*.shp, Polygon): base arcpy.Describe(shp).baseName out rE:\clip_out \\ base _clip.tif arcpy.Clip_management( in_rasterrE:\DOM\dom.tif, rectangle#, out_rasterout, in_template_datasetshp, nodata_value0, clipping_geometryClippingGeometry, maintain_clipping_extentMAINTAIN_EXTENT )参数说明rectangle 传#表示不使用矩形范围范围来自模板要素。clipping_geometry 设 ClippingGeometry输出才沿要素边界裁剪默认值会按要素外接矩形裁黑边就是这样产生的。nodata_value 把背景统一置 0。做直方图统计或模型训练前这个 0 值要预先约定好。env.compression LZWTIFF 输出体积会小很多对遥感影像尤其明显。裁剪完用 arcpy.Describe 对比要素范围和输出栅格范围左右端点的差值应该在一个像元以内shp_ext arcpy.Describe(shp).extent ras_ext arcpy.Describe(out).extent print(abs(shp_ext.XMin - ras_ext.XMin)) print(abs(shp_ext.XMax - ras_ext.XMax))差值明显偏大时优先检查 in_template_dataset 和 clipping_geometry 两个参数是否真的传进去了。5.3 上万要素卡住先查锁、缓存和过滤条件数据量大时脚本卡住通常有三类原因。处理手段如下要素类被编辑器或后台地图锁住时脚本开头执行arcpy.ClearWorkspaceCache_management(rE:\project\result.gdb)清理缓存清理不了就先关闭打开该数据的地图文档再重新跑。临时文件堆积时把中间结果写在 scratchWorkspace收尾统一用arcpy.Delete_management删除。游标遍历数量过大时先用 MakeTableView 加 SQL 过滤再统计。用 where_clause 把行数减到最小比优化循环体的收益大得多。最后是批量验证技巧脚本工具跑完后用原始数据和脚本输出各做一次 Statistics_analysis对拍 SUM 和 COUNT。对拍一致后把验证逻辑单独写成 check_result.py放到批处理流程最末端每次跑完自动出校验报告。本文还有配套的精品资源点击获取