首页 GIS基础理论 ArcPy批量出图:arcpy.mp导出PDF和批量制图

ArcPy批量出图:arcpy.mp导出PDF和批量制图

作者: GIS研习社 更新时间:2026-06-10 08:40:05 分类:GIS基础理论

做县区图册、乡镇专题图、巡查成果图或项目汇报图时,ArcPy批量出图可以把几十到几百张地图从手动导出变成可复现流程。真正稳定的做法不是让脚本从零画一张图,而是在 ArcGIS Pro 中先做好 APRX 模板、布局、图层样式和地图系列,再用 arcpy.mp 控制范围、文字、图层和 PDF 导出。

本文围绕一个常见场景展开:已经有行政区边界、专题数据和 ArcGIS Pro 版式模板,需要按区县或项目单元批量生成 PDF。我们会讲清楚 arcpy.mp 导出 PDF 的对象关系、批量导出多个 Layout 的写法、Map Series 按页输出的写法,以及脚本失败时应该先查哪些地方。

ArcPy批量出图与arcpy.mp导出PDF批量制图流程图
建议配图展示 APRX 模板、Layout、Map Series、arcpy.mp 脚本和 PDF 成果之间的批量制图关系。

问题背景:为什么 ArcPy批量出图比手动导出稳定

手动导出地图最容易出错的地方不是“点错按钮”,而是每张图的范围、比例尺、标题、图层显隐、图例、输出分辨率和文件名必须保持一致。图件数量一多,人很难保证每次操作完全相同。某一页忘记改标题,某一页缩放比例不同,某一页 PDF 没嵌入字体,最后都会变成返工。

ArcPy批量出图适合解决这种重复性制图问题:同一套版式、同一套符号系统、同一类输出格式,只是每张图的空间范围、标题文字、查询条件或页码不同。脚本把这些变量整理成循环,输出结果就更容易检查、复跑和归档。

但要注意,ArcPy 不是排版设计软件。它更适合驱动已经设计好的 ArcGIS Pro 项目。也就是说,图框、指北针、比例尺、图例、动态文本、专题样式、页面尺寸和地图系列,最好先在 ArcGIS Pro 里调好,再交给脚本批量执行。

核心原理:PDF 导出依赖 APRX、Layout 和 Map Series

arcpy.mp 是 ArcGIS Pro 中用于地图自动化的 ArcPy 子模块。它的入口通常是 arcpy.mp.ArcGISProject,也就是一个 .aprx 工程。工程里可以包含多个 Map、多个 Layout、图层、表、样式和地图系列。脚本通过这些对象找到需要操作的布局,再导出 PDF。

批量 PDF 输出的核心对象关系可以这样理解:

  • ArcGISProject:代表一个 ArcGIS Pro 工程,是脚本访问地图、布局和工程属性的入口。
  • Map:代表地图内容,包括图层、表、坐标系和图层顺序。
  • Layout:代表一张页面版式,包含地图框、标题、图例、比例尺、图片和文字元素。
  • MapFrame:Layout 中承载地图的地图框,可以控制显示范围和比例尺。
  • Map Series:地图系列,用索引图层驱动分页,适合行政区图册、分幅图和项目单元图册。
  • ExportFormat:导出格式对象,例如 PDF、PNG、JPEG、TIFF,用来设置输出路径、分辨率、字体和图层属性。

如果使用较新的 ArcGIS Pro 环境,建议优先使用 arcpy.mp.CreateExportFormat("PDF") 创建 PDF 格式对象,再调用 layout.export(pdf)mapSeries.export(pdf)。很多旧教程会写 exportToPDF,它在旧脚本中仍常见,但新项目更适合按当前 arcpy.mp 的 export 方法组织代码。

批量制图的关键不是把所有排版动作都写进 Python,而是让 ArcGIS Pro 模板负责版式,ArcPy 脚本负责批量替换变量和导出。

ArcPy批量出图准备:模板工程、图层和版式命名

开始写脚本前,先把 ArcGIS Pro 工程整理成可被脚本稳定引用的状态。很多导出失败并不是代码复杂,而是模板工程里对象名称混乱、图层数据源断开、布局元素没有命名,导致脚本找不到正确对象。

  1. 保存一个专用 APRX 模板。不要直接在生产工程上反复试脚本,可以另存为 atlas_template.aprx,先保证手动打开时每张图都能正常显示。
  2. 给 Layout 起唯一名称。例如 A3_乡镇专题图A4_项目位置图。不要让多个布局同名,也不要依赖列表顺序猜测第几个布局。
  3. 给 MapFrame 和文本元素命名。例如地图框叫 主地图框,标题文本叫 图名,日期文本叫 制图日期。脚本会用这些名称定位元素。
  4. 检查图层数据源。所有图层都应能在当前机器上访问,路径、数据库连接和网络盘权限要提前确认。
  5. 固定输出规格。页面尺寸、方向、比例尺规则、分辨率、字体、图例显示和 PDF 命名规则,都要在脚本前确定。

ArcPy批量出图来说,模板越规范,脚本越短。不要把“修正图例位置”“重新设计标题样式”“临时改符号”放进批处理脚本里,否则后期维护会非常困难。

arcpy.mp导出PDF:批量导出多个 Layout

最简单的需求是:一个 APRX 工程里已经有多个布局,每个布局都设计好了,只需要一次性导出成多个 PDF。这类 arcpy.mp导出PDF 不需要地图系列,只要遍历 aprx.listLayouts() 即可。

import arcpy
from pathlib import Path

aprx_path = r"D:\gis_projects\county_atlas\atlas_template.aprx"
out_dir = Path(r"D:\gis_projects\county_atlas\output_pdf")
out_dir.mkdir(parents=True, exist_ok=True)

aprx = arcpy.mp.ArcGISProject(aprx_path)

for layout in aprx.listLayouts():
    file_name = layout.name
    for bad in ["\\", "/", ":", "*", "?", '"', "<", ">", "|"]:
        file_name = file_name.replace(bad, "_")

    pdf_path = out_dir / f"{file_name}.pdf"
    pdf = arcpy.mp.CreateExportFormat("PDF", str(pdf_path))
    pdf.resolution = 300
    pdf.embedFonts = True
    pdf.georefInfo = True
    pdf.setLayersAndAttributes("LAYERS_ONLY")

    layout.export(pdf)
    print(f"exported: {pdf_path}")

del aprx

这段脚本适合导出一批已经排好的专题图。它做了三件关键事:第一,用 listLayouts() 获取所有布局;第二,把 Layout 名称处理成合法文件名;第三,为每张图创建 PDF 输出对象并设置分辨率、字体和地理参考信息。

如果只想导出某一个布局,不要写 aprx.listLayouts()[0] 这种不稳定写法。更稳妥的是通过唯一名称查找:

layout = aprx.listLayouts("A3_乡镇专题图")[0]

这样即使以后工程里新增了布局,脚本也不会因为列表顺序变化而导出错对象。

arcpy批量导出地图:用 Map Series 按行政区分页

如果要按乡镇、街道、网格、分幅号或项目单元输出一套图册,优先考虑 ArcGIS Pro 的 Map Series。它用一个索引图层驱动每一页的范围、页名和动态文本,比手工循环设置范围更稳。

arcpy批量导出地图的典型流程是:先在 ArcGIS Pro 中启用地图系列,选择索引图层和名称字段,调好动态标题、页码、图例约束和地图框范围;确认手动预览每页都正常后,再用 arcpy.mp 批量导出。

import arcpy
from pathlib import Path

aprx = arcpy.mp.ArcGISProject(r"D:\gis_projects\county_atlas\county_atlas.aprx")
layout = aprx.listLayouts("A3_乡镇图册")[0]
series = layout.mapSeries

if series is None or not series.enabled:
    raise RuntimeError("这个布局没有启用 Map Series,请先在 ArcGIS Pro 中配置地图系列。")

out_dir = Path(r"D:\gis_projects\county_atlas\pdf_by_town")
out_dir.mkdir(parents=True, exist_ok=True)

pdf = arcpy.mp.CreateExportFormat("PDF")
pdf.resolution = 300
pdf.embedFonts = True

options = arcpy.mp.CreateExportOptions("MAPSERIES")
options.setExportPages("CURRENT")

for page_number in range(1, series.pageCount + 1):
    series.currentPageNumber = page_number
    page_name = str(series.pageRow.NAME)
    clean_name = page_name
    for bad in ["\\", "/", ":", "*", "?", '"', "<", ">", "|"]:
        clean_name = clean_name.replace(bad, "_")

    pdf.filePath = str(out_dir / f"{page_number:03d}_{clean_name}.pdf")
    series.export(pdf, options)
    print(f"exported page {page_number}: {page_name}")

del aprx

上面代码每次把地图系列切到当前页,再导出当前页 PDF。示例里的 NAME 是索引图层字段名,实际项目中要替换成你的页名字段,例如 TOWN_NAMEGRID_IDMAP_NO

如果希望输出一个多页 PDF 图册,可以不用循环每页文件名,直接让 Map Series 导出全部页面:

pdf = arcpy.mp.CreateExportFormat(
    "PDF",
    r"D:\gis_projects\county_atlas\乡镇专题图册.pdf"
)
pdf.resolution = 300
pdf.embedFonts = True

series.export(pdf)

这种方式适合正式图册归档。逐页 PDF 适合分发给不同负责人、上传系统或后续单页审核。选择哪一种,取决于成果交付方式。

arcpy批量制图:更新标题、范围和图层可见性

并不是所有项目都适合 Map Series。有些专题图需要按业务规则切换图层、修改标题、调整范围、替换数据源,或者不同页面使用不同专题字段。这时可以用脚本直接控制布局元素,完成更灵活的 arcpy批量制图

import arcpy
from pathlib import Path

aprx = arcpy.mp.ArcGISProject(r"D:\gis_projects\landuse\landuse_template.aprx")
layout = aprx.listLayouts("A3_专题图模板")[0]
map_frame = layout.listElements("MAPFRAME_ELEMENT", "主地图框")[0]
title = layout.listElements("TEXT_ELEMENT", "图名")[0]

boundary_fc = r"D:\gis_projects\landuse\data.gdb\town_boundary"
target_layer = map_frame.map.listLayers("乡镇边界")[0]

out_dir = Path(r"D:\gis_projects\landuse\pdf")
out_dir.mkdir(parents=True, exist_ok=True)

with arcpy.da.SearchCursor(boundary_fc, ["NAME", "SHAPE@"]) as rows:
    for name, shape in rows:
        safe_value = name.replace("'", "''")
        target_layer.definitionQuery = f"NAME = '{safe_value}'"

        file_name = name
        for bad in ["\\", "/", ":", "*", "?", '"', "<", ">", "|"]:
            file_name = file_name.replace(bad, "_")

        title.text = f"{name}土地利用现状图"
        map_frame.camera.setExtent(shape.extent)
        map_frame.camera.scale *= 1.10

        pdf_path = out_dir / f"{file_name}土地利用现状图.pdf"
        pdf = arcpy.mp.CreateExportFormat("PDF", str(pdf_path))
        pdf.resolution = 300
        pdf.embedFonts = True
        layout.export(pdf)

target_layer.definitionQuery = ""
del aprx

这段代码的思路是用边界要素逐个驱动出图:按名称过滤目标图层,更新标题,把地图框缩放到当前要素范围,再输出 PDF。它适合页面逻辑比较特殊的项目,但也更依赖脚本质量。字段名、查询语句、文件名、比例尺规则和异常处理都要认真检查。

如果每页只是按索引范围切换,Map Series 更省心;如果每页要切换多个图层、多个标题字段或多个专题变量,自定义循环更灵活。不要一开始就写很复杂的循环,先判断 ArcGIS Pro 自带地图系列能不能满足需求。

常见坑:导出失败、空白 PDF 和字体问题

批量脚本出错时,不要只盯着最后一行报错。制图自动化涉及工程、数据、版式和输出路径,任何一处不规范都可能失败。

  • 使用 CURRENT 运行位置不对。ArcGISProject("CURRENT") 只适合在 ArcGIS Pro 内部 Python 窗口或脚本工具中引用当前工程。独立脚本更建议写完整 .aprx 路径。
  • Layout 或元素名称不唯一。listLayouts()listElements() 返回的是列表。如果同名对象很多,脚本可能拿到错误对象。
  • 地图系列没有启用。layout.mapSeries 可能是 None,也可能存在但未启用。导出前必须检查。
  • 输出文件名包含非法字符。行政区名称、项目名称里可能有斜杠、冒号、引号等字符,写入 PDF 前要清理。
  • PDF 空白或范围不对。常见原因是地图框名称找错、范围设置到空几何、图层定义查询过滤掉全部要素,或图层数据源断开。
  • 中文字体替换。正式交付的 PDF 建议设置 embedFonts = True,并确认制图机器安装了模板使用的字体。
  • 文件体积过大。高分辨率影像、复杂矢量和图层属性会放大 PDF。可根据交付需求调整分辨率、图层属性、影像压缩和是否保留地理参考信息。
  • 比例尺不一致。如果项目要求统一比例尺,不要只用 setExtent,还要明确设置或取整 map_frame.camera.scale
  • 没有先手动导出样张。批处理前至少手动导出 1 到 3 张代表性页面,确认图例、标注、范围、PDF 字体和输出质量没有问题。

工具和方法对比:手动导出、Map Series 和脚本循环

不同出图任务不需要同一种方法。下面的对比可以帮助你选择更稳的流程。

方法 适合场景 优点 限制
手动导出 Layout 只导出一两张图,或临时检查样张 直观,适合设计阶段快速调整 数量一多容易漏改标题、范围和输出参数
ArcGIS Pro Map Series 行政区图册、标准分幅、网格巡查图、项目单元图册 动态文本、页码、索引范围和图册逻辑稳定 复杂业务条件切换不如脚本循环灵活
arcpy.mp 遍历 Layout 一个工程里已有多张排好版的专题图 代码短,适合统一导出 PDF、PNG 或 TIFF 不负责自动生成页面内容,前期版式必须已经做好
arcpy.mp 自定义循环 每页需要修改标题、查询条件、图层显隐、范围或数据源 灵活,能嵌入项目业务规则 更容易受字段、查询、文件名和异常数据影响
旧式 exportToPDF 脚本 维护历史项目或旧版单位环境 旧代码存量多,容易在老项目中见到 新项目建议优先采用 export 格式对象写法,便于后续扩展

如果是标准图册,推荐先用 Map Series;如果是已有多个布局,推荐遍历 Layout;如果每页规则都不同,再考虑自定义脚本循环。方法选对了,脚本会简单很多。

实用检查清单:批处理前后分别看什么

运行脚本前

  • APRX 是否能在 ArcGIS Pro 中正常打开,所有图层是否无断链。
  • Layout、MapFrame、TextElement、目标图层名称是否唯一。
  • 地图系列是否已经启用,索引图层和页名字段是否正确。
  • 输出目录是否存在,脚本账号是否有写入权限。
  • 样张 PDF 是否已经手动导出并检查字体、图例、比例尺和范围。

运行脚本时

  • 打印当前导出的页码、页名和输出路径,方便定位失败页面。
  • 对空几何、空名称、重复名称和非法文件名做处理。
  • 优先从少量页面测试,再扩大到全部页面。
  • 不要在同一个输出目录里混放旧版和新版 PDF,避免误判结果。

导出完成后

  • 核对 PDF 数量是否等于 Layout 数量、地图系列页数或输入要素数量。
  • 抽查首页、中间页、末页,以及边界特别大或特别小的页面。
  • 检查中文字体、图例、标注、比例尺、页码和图名是否正确。
  • 检查 PDF 文件大小是否异常,异常过小可能是空白页,异常过大可能需要调整导出参数。
  • 把脚本、APRX 模板、输入数据版本和输出结果一起归档,保证下次可以复跑。

FAQ:批量出图、PDF 导出和自动制图

ArcPy批量出图一定要会写复杂 Python 吗?

不一定。标准图册的核心通常是 ArcGIS Pro 模板和 Map Series,Python 只负责批量导出和少量参数控制。初学者可以先从遍历 Layout 导出 PDF 开始,再逐步加入标题替换、范围控制和图层查询。

arcpy.mp导出PDF时,应该用 exportToPDF 还是 export?

新项目建议优先使用 CreateExportFormat("PDF")export 的写法,参数更容易和其他格式统一管理。旧脚本里常见 exportToPDF,维护历史项目时可以继续理解它,但不要把旧写法当作唯一方案。

arcpy批量导出地图为什么导出的页面都是同一个范围?

常见原因是 Map Series 没有启用、循环里没有更新 currentPageNumber,或者自定义循环中只改了标题,没有调用 map_frame.camera.setExtent()。如果用地图系列,还要确认索引图层和页名字段设置正确。

arcpy批量制图能不能自动修改图例和标注?

可以控制一部分图例、图层可见性、定义查询和文本元素,但不建议把复杂排版全部写进脚本。更稳的方式是在模板里先调好图例样式、标注规则和动态文本,脚本只替换变量和导出。

批量导出的 PDF 文件很大怎么办?

先判断交付是否必须保留图层、属性和地理参考信息。如果只是普通审阅图,可以降低分辨率、关闭部分 PDF 图层属性或调整影像压缩;如果是正式 GIS 成果,则要在文件大小和可编辑、可量测能力之间做取舍。

脚本在 ArcGIS Pro 里能跑,独立运行却失败怎么办?

先检查是否使用了 ArcGISProject("CURRENT")。它只适合在 ArcGIS Pro 内部引用当前工程。独立运行时应使用完整 APRX 路径,并确保调用的是 ArcGIS Pro 自带的 Python 环境,而不是普通系统 Python。

结论:把批量制图拆成模板和脚本两部分

ArcPy批量出图最稳的思路,是让 ArcGIS Pro 负责制图表达,让 arcpy.mp 负责自动化执行。先把 APRX 模板、Layout、Map Series、图层样式和动态文本做好,再用脚本批量设置页面、范围、标题和 PDF 输出参数。

如果只是统一导出已有布局,用 arcpy.mp 遍历 Layout 导出 PDF 就够;如果要按行政区或网格生成图册,用 arcpy批量导出地图 的 Map Series 流程更稳;如果每页还有复杂业务规则,再写自定义 arcpy批量制图 循环。把这三类场景分清楚,脚本会更短,成果也更容易复核。

相关文章