资讯详情

ArcGIS Python脚本编程:从arcpy入门到批处理自动化

📅 2026/9/17 15:13:09 | 华诺云谱 👁 阅读
ArcGIS Python脚本编程:从arcpy入门到批处理自动化
简介这份PDF教程专为初次接触ArcGIS Python脚本的GIS初学者与从业者编写围绕“如何用Python自动化地理处理任务”展开从最基础的Python语法讲起逐步过渡到ArcGIS工具集成能帮助读者减少重复操作、提升数据处理效率。资源为单份PDF文档共1个文件大小1.08MB目录结构清晰涵盖数学运算符、字符串操作、模块使用、函数定义、流程控制等Python基础以及创建地理处理对象、调用工具箱、在ModelBuilder中嵌入脚本、用PythonWin调试等ArcGIS实战内容编排循序渐进适合自学与教学参考。文档还包含使用Describe与Exists获取数据信息等实用章节方便读者在批量处理与排错时查阅。目前已有1001人学习下载对于希望快速上手ArcGIS Python脚本的零基础用户而言是一份内容紧凑、实操导向的入门资料。1. 为什么说 Python 脚本是 ArcGIS 的“第二语言”接触 ArcGIS 超过一年的用户基本都会撞上同一堵墙重复操作太多。裁剪、投影、批量出图、字段计算点鼠标点到手酸换一台电脑就得重来一遍。而 ArcGIS 内置的 Python 环境就是把这堵墙拆掉的那把锤子。这里的核心不是“写程序”而是把地理处理工具按顺序、按参数、按条件串起来交给脚本去跑。ArcGIS 里的 Python 脚本本质上是对地理处理框架Geoprocessing Framework的二次组织桌面端的 ArcToolbox 里每个工具背后都是一个 Python 可调用的函数你通过arcpy这个站点包在脚本里完成“选工具、填参数、执行、检查结果”四步。这套体系从 ArcGIS Desktop 10.x 时代一直延伸到现在 ArcGIS Pro 的 arcpy.mp 和 arcpy.da语法骨架没有断代学会的脚本在两个平台上都能改得过来。这篇内容适合已经能完成基础制图和空间分析、但还没认真碰过脚本箱的人群也适合想把手头批处理工作统一收编的老手。看完之后你能自己写出一个能跑完整地理处理的脚本并知道在报错时该看日志里的哪一行。2. 从一段最小脚本理解 arcpy 的运行逻辑2.1 在 ArcGIS 里跑 Python 的三种常见姿势ArcGIS 生态里跑 Python最常见的有三处ArcMap / ArcCatalog 里的 Python 窗口、ArcGIS Pro 的 Python 控制台、以及独立安装的 Python IDE如 PyCharm里直接连 ArcGIS 的 Python 解释器。这三种姿势对应的调试效率完全不一样。Python 窗口适合快速试单个工具每输入一行按回车就能看到工具是否执行成功控制台体验接近 Jupyter支持多行编辑和变量查看独立 IDE 适合写完整脚本能断点调试、查看变量类型但前提是解释器要指对——Windows 上 ArcGIS Desktop 10.x 自带的是 Python 2.7 的 32 位版本ArcGIS Pro 则使用独立的 conda 环境默认叫 arcgispro-py3通常是 Python 3.7。这个版本差异是新手最大的坑写脚本前先确认目标机器上 ArcGIS 自带解释器的版本不然装第三方库时容易装到别的 Python 里import arcpy 直接报 ModuleNotFoundError。2.2 import arcpy 之后到底发生了什么# -*- coding: utf-8 -*- import arcpy arcpy.env.workspace rC:\GIS_Project\data.gdb fc_list arcpy.ListFeatureClasses() print(当前工作空间中的要素类数量: , len(fc_list)) for fc in fc_list: print(fc)这段代码一共做了三件事导入 arcpy 站点包、设定当前工作空间、列出该空间下所有要素类。执行import arcpy时ArcGIS 会把所有工具箱里的工具类加载为 Python 可调用的模块对象这个加载过程本身就有开销所以脚本首次执行时常会看到一两秒的停顿不是卡死。arcpy.env.workspace是一个全局环境变量它决定了后续所有不带绝对路径的工具参数的默认解析位置。在这里给成data.gdb后面的ListFeatureClasses()就不用再写完整路径。arcpy.env里还有很多类似的全局开关比如arcpy.env.overwriteOutput、arcpy.env.outputCoordinateSystem它们统称“环境设置”会在后面具体讲。提示r...是把字符串声明为原始字符串反斜杠不会被转义。Windows 路径一律用这种写法或者把反斜杠换成正斜杠否则\t、\n这类转义符会破坏路径。2.3 工具的参数传递约定工具箱里什么顺序脚本里就什么顺序ArcGIS 所有地理处理工具的参数顺序跟工具箱对话框里的排列顺序严格一致。比如Buffer_analysis工具在工具箱里依次是“输入要素、输出要素、缓冲区距离、融合方式”那么脚本调用就是arcpy.Buffer_analysis( in_featuresrC:\GIS_Project\roads.shp, out_feature_classrC:\GIS_Project\roads_buf.shp, buffer_distance_or_field500 Meters, dissolve_optionALL )这里有两个容易出错的地方。第一参数名比如in_features可以省略只按位置传递但一旦省略顺序绝对不能乱混用位置参数和关键字参数时位置参数要全部放在前面。第二距离字段500 Meters是字符串形式的线性单位不是纯数字——写500会被当成 500 个地图单位在无投影的经纬度数据里就是 500 度这个错误几乎每个新手都会遇到一次。你可以在 ArcGIS Pro 的 Geoprocessing 窗格底部选中某个工具点击“复制 Python 命令”工具会把它当时的所有参数自动翻译成一段可执行的 Python 代码这是最稳妥的“抄作业”方式比自己记忆参数名可靠得多。3. 驱动数据与 GIS 数据的遍历技巧3.1 用 arcpy.da.Walk 代替 os.walk 遍历 GIS 数据桌面端的 Python 标准库里有os.walk能遍历文件夹系统但它不认识 GDB、SDE 这类地理数据库也不认识要素集。ArcGIS 10.0 以后的 arcpy.da 模块专门提供了一个Walk生成器专门解决“我在这个根目录下有哪些要素类、哪些栅格、哪些数据集”这个问题。它的工作方式可以类比成地理数据库世界里的os.walk从给定的工作空间出发递归向下走每层返回三个值——当前路径、目录列表、数据集列表。import arcpy workspace rD:\GIS_Data\各县数据 for dirpath, dirnames, filenames in arcpy.da.Walk(workspace, datatypeFeatureClass): for fc in filenames: full_path arcpy.os.path.join(dirpath, fc) print(发现要素类: full_path)注意代码里的arcpy.os.path.joinarcpy 里内置了 os 模块的引用所以直接arcpy.os就能用。Walk的第二个参数datatype用来过滤数据类型可填FeatureClass、RasterDataset、Table等。Walk返回的路径已经是 ArcGIS 能直接识别的描述形式比如D:\GIS_Data\各县数据\某县.gdb\道路不需要再手动拼接.shp后缀。这里是遍历脚本的地基几乎所有批量操作都要从这一层开始。3.2 SearchCursor / UpdateCursor 的必调参数与常见坑当遇到“遍历要素类每一行并读取或修改属性”这个需求时大家最自然的做法是打开属性表手动算。脚本里要对属性表逐行操作用的是游标Cursor。arcpy.da.SearchCursor是查询型游标UpdateCursor是更新型游标两者规范用法是先传入要素类路径再传入字段名列表然后对返回的行做迭代import arcpy fc rC:\GIS_Project\landuse.shp fields [FID, AREA, LAND_TYPE] with arcpy.da.SearchCursor(fc, fields) as cursor: for row in cursor: fid, area, land_type row if area 10000: print(大面积地块: {} ({} 平方米, 类型: {}).format(fid, area, land_type))这里with ... as cursor是资源管理器的标准写法离开代码块后游标会自动关闭并释放文件锁。有三个高频问题第一字段名必须完全一致写错一个字母就报ERROR 999999而且一定带上FID字段时要注意FID是只读字段不能用于UpdateCursor的写入第二SearchCursor返回的每一项都是元组需要用索引或解包去取不要尝试用cursor[0]取行第三UpdateCursor每次修改完一行后要调用cursor.updateRow(row)否则修改只在内存里不会落盘。真实项目里我一般会把要反复修改要素属性的需求先写成函数再包一层循环重用性比直接写一堆流程代码高得多。3.3 将“遍历脚本”改造成批量处理工具的通用模板把上面两节的内容拼起来就是一个标准的批量处理骨架Walk 找数据 → SearchCursor 读属性 → 判断条件 → 执行某个地理处理工具。我经常在项目里用这个模板批量修复大量图斑的投影和坐标单位问题import arcpy arcpy.env.overwriteOutput True def process_feature_class(fc, output_dir): 对单个要素类执行投影输出到指定目录 desc arcpy.Describe(fc) if desc.spatialReference.name WGS_1984_UTM_Zone_50N: return out_name arcpy.Describe(fc).baseName _UTM50.shp out_path arcpy.os.path.join(output_dir, out_name) arcpy.Project_management(fc, out_path, WGS 1984 UTM Zone 50N) return out_path root rD:\GIS_Data\原始数据 output_dir rD:\GIS_Data\投影结果 for dirpath, dirnames, filenames in arcpy.da.Walk(root, datatypeFeatureClass): for fc in filenames: full_path arcpy.os.path.join(dirpath, fc) result process_feature_class(full_path, output_dir) if result: print(已处理: result)这个模板本身不复杂但有两个隐藏要点值得提。arcpy.Describe是获取数据元信息的万能钥匙它返回一个 Describe 对象里面包含了数据的所有属性——空间参考、要素类型、字段列表、几何类型等。判断“数据是否已经被处理过”靠它最可靠不用看一眼文件再试跑一遍。另一个是arcpy.env.overwriteOutput True默认情况下 ArcGIS 不允许覆盖已有数据集脚本第二次运行时往往会卡在输出路径已存在这个问题上把这个开关打开输出可以反复覆盖适合批处理开发阶段的反复尝试。4. 用 arcpy.mp 重构制图与出图工作流4.1 布局元素、图层符号系统与元素定位的脚本控制日常制图里最费时间的环节往往是布局调整图名对不对、比例尺放哪、指北针多大、图例有没有盖住主图。arcpy.mpArcGIS Pro 的制图模块Desktop 10.x 对应 arcpy.mapping就是冲着这些问题来的。这个模块的设计思路是把一个.aprxArcGIS Pro 工程文件当作一个对象树来操作工程 → 地图 → 图层 → 符号布局 → 元素 → 文本/图片/图例。以下是一段直接修改现有工程布局中标题文本框内容的脚本import arcpy aprx arcpy.mp.ArcGISProject(rC:\GIS_Project\map_template.aprx) layout aprx.listLayouts(报告版式)[0] title_element layout.listElements(TEXT_ELEMENT, 标题)[0] title_element.text 2025年土地变更调查成果图 aprx.save()listLayouts(报告版式)里的参数是按名称过滤布局如果工程里只有一个布局括号里可以直接留空但返回的是列表所以记得带[0]。listElements同理第一个参数传元素类型第二个参数传元素名称。这里的“元素名称”是你在 ArcGIS Pro 的布局视图里选中元素后在“布局”选项卡的属性窗格里看到的那个名字不是显示文字。显示文字靠的是.text属性不同元素的属性不同TEXT_ELEMENT有.textPICTURE_ELEMENT有.imageLEGEND_ELEMENT有.title。脚本化之后一套版式可以无限复用替换作图的人只需要维护好模板里的元素命名不再需要每期图手动打字、手动挪框。4.2 批量导出地图到同一布局的三种输出格式输出格式是出图脚本的重头戏。同一个布局对应不同数据时往往要求同时产出 PDF、JPG 和 PNG 三种格式。arcpy.mp 的布局对象有一个exportToPDF方法地图对象有exportToJPEG和exportToPNG。一般处理逻辑是先引用某个已经做好布局的工程文件然后循环替换数据源最后导图。常用形式是import arcpy aprx arcpy.mp.ArcGISProject(rC:\GIS_Project\outmap.aprx) layout aprx.listLayouts(A3横版)[0] output_folder rC:\GIS_Project\output # 导出PDF分辨率300dpi不压缩栅格 layout.exportToPDF( arcpy.os.path.join(output_folder, 最终成果.pdf), resolution300, image_qualityBEST, compress_vectorsFalse ) # 导出PNG仅布局中某个地图框的地图视图 mf layout.listElements(MAPFRAME_ELEMENT)[0] mf.camera.setExtent(mf.getLayerExtent(mf.map.listLayers(道路)[0])) layout.exportToPNG( arcpy.os.path.join(output_folder, 道路专题.png), resolution150 )这段代码的关键在mf.camera.setExtent(...)。地图框Map Frame本身有“相机”概念类似于站在地图上方某个位置往下看getLayerExtent取的是某个图层的空间范围把这两者组合就能让导出图自动缩放到目标图层范围不需要手动去布局里调整缩放到哪。这个能力在做每村一幅图、每乡镇一幅图的批量任务时尤其值钱——以前手动做 30 个乡镇要一天脚本只需要维护好图层名字的对应关系。注意在 ArcMap 10.x 环境下对应 API 是arcpy.mapping方法名略有差异核心逻辑一致。4.3 更新数据源而不打开工程文件在一个成熟的出图流程里工程文件只是模板最终输出的图往往是“当前月的数据、固定布局”的组合。这时需要一个能不改动工程文件内其他元素、只替换某个图层数据源的操作。在 arcpy.mp 中可以用updateConnectionProperties方法它接收三个参数旧数据源连接、新数据源连接、是否校验匹配项。import arcpy aprx arcpy.mp.ArcGISProject(rC:\GIS_Project\月度出图.aprx) m aprx.listMaps(主图)[0] for lyr in m.listLayers(): # 只替换以统计_开头的图层 if lyr.name.startswith(统计_): old_conn lyr.connectionProperties new_conn { connection_info: { database: rC:\GIS_Project\2025年10月.gdb }, dataset: lyr.datasetName } lyr.updateConnectionProperties(old_conn, new_conn) print(图层 [{}] 已切换数据源到: {}.format(lyr.name, new_conn)) aprx.saveACopy(rC:\GIS_Project\月度出图_10月.aprx)用saveACopy而不是save这个细节很关键它生成一个副本文件保留原模板不被改动方便下个月继续用。执行完以后建议用arcpy.mp.ArcGISProject重新加载这个副本再listLayers检查各图层的dataSource属性确认路径是否正确这是脚本写完以后最重要的验证步骤。提示updateConnectionProperties在数据源结构发生变化时比如字段被删会失败报错信息通常会指向某个图层定位方式是逐个图层执行而不是整个列表一次更新这样能把报错范围缩到最小。5. 几何对象、字段计算与地图代数5.1 直接用几何属性生成面积字段的常见写法在很多项目里图斑面积字段要么是别人填的、要么是早期手工数字化时估算的跟真实几何面积对不上直接用来出统计表会被审计质疑。这时最稳妥的做法是在 ArcGIS 里用脚本统一按几何对象计算面积。这个需求在旧版 Desktop 里就得靠字段计算器选择 Python 解析器但脚本里更直接import arcpy fc rC:\GIS_Project\landuse.shp arcpy.AddField_management(fc, SHAPE_AREA_ACT, DOUBLE) arcpy.CalculateField_management( fc, SHAPE_AREA_ACT, !shape.area!, PYTHON_9.3 )第四行参数PYTHON_9.3是 Desktop 10.x 里常用的旧版 Python 表达式解析器ArcGIS Pro 里一般写成PYTHON3。字段计算表达式!shape.area!中字段名用英文感叹号包起来shape是要素类内置的几何字段.area属性直接返回要素的平面面积单位取决于数据框的坐标系。需要强调一点!shape.area!得到的是投影坐标系下的面积如果你的数据是经纬度GCS_WGS_1984这个面积的单位是“平方度”数值会失真这时要先做投影变换或者在计算前用arcpy.env.outputCoordinateSystem指定一个投影坐标系。5.2 几何对象的空间关系判断在其他工具中的复用关于“某个点是否落在某个面内”ArcGIS 图形交互里是“选择”工具一键就完成但放到脚本里就需要自己写空间关系逻辑。arcpy 的 Geometry 对象自带一组空间关系方法contains、within、crosses、intersects、overlaps、touches等全部返回布尔值。这个方法串起了一个特别常用的操作——批量给点要素打上所在面的“行政区代码”字段import arcpy point_fc rC:\GIS_Project\poi.shp polygon_fc rC:\GIS_Project\boundary.shp fields [SHAPE, AD_CODE] point_fields [SHAPE, AD_CODE_CALC] arcpy.AddField_management(point_fc, AD_CODE_CALC, TEXT, field_length20) # 先把面要素读入内存 polygon_list [] with arcpy.da.SearchCursor(polygon_fc, [SHAPE, AD_CODE]) as cursor: for row in cursor: polygon_list.append(row) # 每个元素: (Polygon几何对象, 行政区代码) with arcpy.da.UpdateCursor(point_fc, point_fields) as cursor: for point_row in cursor: point_geom point_row[0] in_code None for poly_geom, poly_code in polygon_list: if poly_geom.contains(point_geom): in_code poly_code break point_row[1] in_code cursor.updateRow(point_row)注意SHAPE这个写法。在arcpy.da游标里带后缀的字段名表示要取几何对象本身而不是几何的某个属性。不写SHAPE这个字段游标取出来的几何并不直接可用。这段脚本在数据量不大几千个点、几百个面时足够快当点数量到百万级时contains的逐个遍历就是 O(n*m) 复杂度这时应该改用空间连接工具SpatialJoin_analysis或者在游标外先用SelectLayerByLocation_management做预筛选。5.3 Raster 计算中的地图代数接口栅格处理在 Python 里走的是地图代数Map Algebra接口ArcGIS Pro 里可以通过arcpy.sa模块直接进行波段计算。一个常见的 NDVI归一化植被指数计算脚本如下import arcpy from arcpy.sa import * arcpy.env.workspace rC:\GIS_Project\raster arcpy.env.overwriteOutput True red Raster(land8_red.tif) nir Raster(land8_nir.tif) ndvi Float((nir - red) / (nir red)) ndvi.save(ndvi_result.tif)Raster()把磁盘上的影像文件加载成 Raster 对象Float()把结果强制转成浮点型避免整数相除的截断误差。这里最容易踩的坑是arcpy.sa的*通配符导入和普通arcpy导入混在一起时会出现同名函数冲突比如arcpy.Con和arcpy.sa.Con。解决办法要么是只导入from arcpy.sa import *要么把arcpy.sa明确命名空间调用。此外Raster 计算的临时文件默认放在系统临时目录大量计算前最好设置arcpy.env.scratchWorkspace到一个有足够磁盘空间的本地路径避免 C 盘写满导致的 Failed to create raster dataset 报错。6. 创建自定义工具与脚本工具箱的最后一步固化当脚本在后台稳定跑通以后直接扔给不写代码的同事是不负责任的。ArcGIS 的“参数化”机制可以把脚本包装成工具箱里的工具别人只要在 Geoprocessing 窗格里选输入、填路径就能调起你的脚本完全不用看到 Python 源码。这个固化流程值得花十分钟做一遍因为大部分日常替人跑数据的活到最后都会沉淀成一个自定义工具。创建一个脚本工具箱文件后缀.atbxDesktop 10.x 是.tbx再把.py文件添加为脚本工具然后在工具属性里定义“参数”列表。这里参数顺序必须和脚本里sys.argv[1]、sys.argv[2]的读取顺序一一对应。一个接收输入要素类和输出路径的最小脚本头是这个样子import arcpy import sys input_fc sys.argv[1] output_fc sys.argv[2] arcpy.CopyFeatures_management(input_fc, output_fc)参数类型建议设置成“要素类”而非“字符串”这样 ArcGIS 会自动弹出要素选择框版本兼容性检查也会自动做。设置参数后工具框右下角会出现“环境”按钮这里可以勾选输出坐标系、处理范围等环境设置它们会覆盖脚本里的arcpy.env初始值相当于给工具加了外置开关。脚本里通过arcpy.GetParameterAsText(0)读取的值更规范因为它即使在命令行不传参时也会弹输入框。调试阶段的建议是先加很多print()在 Python 窗口里跑通再改造成参数化脚本。工具在异常时会弹对话框默认只显示最后一行异常加上arcpy.AddError()和arcpy.AddWarning()才能把关键过程信息输出到工具的消息窗口里。最后用arcpy.TestSchemaLock检查目标要素类是否被其他用户锁定这个函数在多人共用一个 SDE 数据库时有奇效它在执行编辑前判断资源锁而不是等UpdateCursor写入时被数据库拒绝——先用几行代码判断比等报错再排查要省太多时间。本文还有配套的精品资源点击获取
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。