用PyQGIS批量导出地图布局

Python
Dr.GIS
wowwwai GIS研习社 · 工具流程与项目排障

用 PyQGIS 批量导出地图布局,核心做法是:先拿到或创建 QgsPrintLayout(继承自 QgsLayout),再用 QgsLayoutExporter 按统一参数写出 PDF、SVG 或 PNG 等文件;在脚本里循环项目中的多个布局,或按不同图层、范围、标题动态生成布局,即可一次导出全部成果图。官方推荐优先走 exporter,而不是直接操作底层 QGraphicsScene。按下面步骤写脚本,就能把重复的“打开布局→导出→换下一张”变成可验收的批处理。

批量导出多份地图布局的概念示意

要解决什么问题、什么时候该用脚本

手工点布局管理器导出,适合一两张图;一旦出现“同一项目几十张专题图、同一套样式换多个行政范围、同一布局换多种输出尺寸”,人工操作又慢又容易漏改比例尺或标题。PyQGIS 批量导出专门解决这类重复劳动:布局对象、页面设置、导出格式与 DPI 都写进脚本,结果可复现、可纳入定时任务或质检流水线。

  • 项目里已有多个命名布局,需要统一导出为 PDF/PNG。
  • 按要素列表(区县、图幅号等)循环改地图范围与标注,再导出。
  • 要固定输出 DPI、纸张、边距,避免同事各自点菜单导致规格不一致。

接口细节可对照 PyQGIS 开发者手册中的布局与打印章节,导出类行为以 QgsLayoutExporter 类文档 为准。

批量导出的可执行步骤

下面按“已有布局批量导出”为主路径说明;若布局不存在,可在循环里动态创建 QgsPrintLayout 并往里加地图项、图例、比例尺后再导出。步骤面向已能在 QGIS 里跑 Python 控制台或脚本工具的用户。

  1. 打开目标工程:用 QgsProject.instance() 取当前项目,或用 read() 加载指定 .qgz/.qgs。确认布局管理器里已有要用的布局名称。
  2. 取出布局:通过 project.layoutManager().layoutByName(“布局名”) 拿到 QgsPrintLayout;若要批量,先列出 layoutManager().layouts() 再过滤名称前缀或标签。
  3. 需要时刷新内容:改地图项的范围(setExtent)、图层可见性、标题文本项内容,并调用 refresh() 或相关更新方法,保证导出前画布与图例一致。
  4. 创建导出器:对每个布局实例化 QgsLayoutExporter(layout)。
  5. 设置导出参数:PDF 用 QgsLayoutExporter.PdfExportSettings(如 dpi、强制矢量等);栅格用 ImageExportSettings(dpi、尺寸);按任务选 exportToPdf、exportToImage 或 exportToSvg。
  6. 循环写出文件:用统一命名规则拼输出路径(例如 布局名_日期_范围.png),检查返回的导出结果枚举是否为成功。
  7. 收尾:关闭或丢弃临时创建的布局,避免内存里堆积大量 QgsPrintLayout;大批量时可适当释放引用并留意日志。

验收标准建议写进脚本注释或质检清单:输出文件数量与布局/要素列表一致;抽样打开 PDF/PNG,核对范围、比例尺、坐标系注记与标题;文件大小与 DPI 符合约定(例如网页用 150 dpi、印刷用更高 dpi,具体以任务书为准)。

从项目到布局再到文件的导出流程示意

格式与参数怎么选

格式选错会导致后续印刷发虚或网页体积过大。下表按常见用途归纳,参数名以 QgsLayoutExporter 相关设置为准,具体字段以当前 QGIS 版本 API 为准。

输出目标 常用方法 关键设置思路 适用场景
PDF exportToPdf 设置合理 DPI;需要可编辑文字时注意字体嵌入与矢量导出选项 报告附件、印刷送厂、归档
PNG/JPEG 等栅格 exportToImage 明确 dpi 或像素宽高;透明背景按需开启 网页插图、幻灯片、快速预览
SVG exportToSvg 注意复杂符号与标注是否被栅格化;大图慎用 后期在矢量软件里微调
  • 同一批图尽量共用同一套 PdfExportSettings / ImageExportSettings,避免“有的 96 dpi、有的 300 dpi”。
  • 纸张与边距在布局的 pageCollection 里统一,而不是每个导出临时改半截。
  • CRS、比例尺分母、指北针是否显示,应在导出前改布局内容,而不是指望导出器自动纠正专题逻辑。

注意点、常见报错与处理

批量脚本最容易栽在“布局名写错、地图项没刷新、路径无写权限、无界面环境下字体/渲染差异”上。按下面排查,通常能快速定位。

  • layoutByName 返回空:名称必须与布局管理器里完全一致(含空格、中英文)。先打印所有 layout.name() 再匹配。
  • 导出成功但图是空的或旧范围:改 extent 后未刷新地图项;确认取到的是正确的 QgsLayoutItemMap,并在导出前更新。
  • PDF/PNG 写入失败:检查目录是否存在、是否只读、文件是否被其他程序占用;路径尽量用绝对路径,避免相对路径随工作目录漂移。
  • 中文乱码或缺字:本机字体与布局里指定字体不一致;在跑脚本的环境安装对应字体,或把文本改成工程内可用字体。
  • 无界面(headless)批量:需按当前 QGIS/PyQGIS 版本正确初始化应用与前缀路径;渲染行为可能与桌面略有差异,应用小样图先验收再放大批。
  • 内存持续上涨:循环里反复 new 布局却不删除;及时从 layoutManager 移除临时布局并避免无意义的大尺寸栅格。

不确定的版本差异,以你安装的 QGIS 自带 PyQGIS API 与上述官方手册为准,不要照搬过旧博客里的 QgsComposition 写法(那是更早一代接口)。

常见问题

可以不打开 QGIS 桌面就跑批量导出吗?

可以。把逻辑写成独立脚本,在正确初始化 QgsApplication 的环境下运行即可;首次部署先用两三张布局试跑,确认字体、图层数据源路径在无界面环境下仍然有效。

已有布局和脚本里新建布局,哪种更适合批量?

版式固定、只换数据范围时,优先复用已有布局,改地图项与文本项再导出,维护成本低。版式本身随专题大变时,再用代码新建 QgsPrintLayout 并添加各布局项。

导出 PDF 和 PNG 要写两套循环吗?

不必。同一循环里对同一个 QgsLayoutExporter 先按 PDF 设置导出,再按图像设置导出即可;注意输出文件名后缀和设置对象不要混用。

怎么确认批量结果全部合格?

脚本记录每次 export 的返回状态与输出路径;再用文件数量校验,并对失败项重试或写入错误日志。人工抽查若干张核对范围、图例和 DPI,作为最终验收。

总结:PyQGIS 批量导出地图布局,抓住 QgsPrintLayout + QgsLayoutExporter 这条主线,用循环统一改内容、统一导出参数,并做好路径与刷新检查。建议先固化一两个“标准布局 + 标准 Pdf/Image 设置”,再扩展到按要素列表出图;上线前用小样本对数量、范围和清晰度做一次验收,再跑全量任务。