☰
ArcGIS图斑批量出图实战:数据驱动页面与arcpy避坑指南
2026/11/3 15:01:20 网站建设 项目流程

简介:《Arcgis按图斑批量出图(按卫片图斑批量出图)》是一份面向地理信息制图、自然资源卫片核查与批处理出图人员的实操文档,主要解决大量图斑逐张手工导出效率低、命名与信息标注易出错的问题。压缩包仅含1个doc文件,大小约29KB,内容紧凑,便于在项目现场或桌面端快速查阅。已有8322人学习,说明其在ArcGIS批量出图场景中具备一定参考价值。文档围绕数据驱动页面、布局动态文本与arcpy脚本导出展开,说明如何按图斑遍历页面并生成JPG或PNG图片,读者可从中了解批量出图的配置思路、脚本组织方式、导出参数调整及结果检查方法,并保留可复用脚本与排错思路,也能参考版本前提与执行注意事项,适合需要提升图斑制图效率的初中级GIS用户参考。

1. 从三百张 JPG 说起:ArcGIS 批量出图这件事,卡人的从来不是脚本

一个卫片图斑层,三百多个多边形,每个图斑要单独出一张 JPG,文件名还得是图斑编号。手工做法是缩放到图斑、调比例尺、导出、改文件名,再重复三百次。做过一次的人都知道,前二十张还有耐心,后面就是纯体力活,而且比例尺会飘、文件名会错、某几张会忘了导出。ArcGIS 批量出图真正卡人的地方,从来不是那八行 Python,而是 Data Driven Pages 有没有配对、索引图层选没选对、arcpy 用的是哪个解释器、最后一页为什么总是漏掉。这套环境装一次能管很久,配错一次能折腾一整天。下面按我实际装过、跑过、翻过车的顺序,把 ArcGIS 10.2 下按图斑批量出图的完整落地过程走一遍,新手能照着走通,熟手能跳过已知的坑。

2. 环境清单:ArcGIS 10.2、Python 2.7 与 Notepad++ 的版本搭配

2.1 版本卡在哪:9.x 直接出局,10.0 勉强,10.2 起步

按图斑批量出图依赖两个东西:ArcMap 里的 Data Driven Pages(数据驱动页面)和 arcpy.mapping 模块。前者是 10.0 才引入的功能,9.3 里没有对应的替代品,用 9.x 想去实现这件事等于从零写 UI,不划算,所以「9 不行」不是保守,是功能缺失。后者 arcpy 同样是 10.0 才随 Desktop 一起发出来的,9.x 时代叫 arcgisscripting,接口完全不是一回事。

10.0 能跑,但内置 Python 是 2.6,脚本里稍微用点新语法就报错,而且各类导出函数缺少后期补上的参数,所以实际落地一般直接上 10.2 及以上。10.2 到 10.8 这一段,Python 都是 2.7,arcpy.mapping 的 API 基本没变,同一份脚本可以横着走。

ArcGIS 版本内置 PythonData Driven Pagesarcpy.mapping是否可用
9.3无(arcgisscripting)不支持无出局
10.02.6支持初版勉强,不建议
10.12.7支持可用可用
10.2 ~ 10.82.7支持稳定推荐

许可级别这块不用太担心,按图斑出图只用到布局导出,ArcView(基础)级别的 Desktop 许可就够,不需要任何扩展模块。我在一台只装了基础许可的机器上跑过完整流程,脚本没报过许可相关的错。真正会拦人的是下面这条:ArcGIS Desktop 是 32 位程序,它自带的 Python 解释器也是 32 位的,而后来单独安装的 64 位后台地理处理(Background Geoprocessing)环境里,arcpy.mapping 是不可用的。也就是说,批量出图的脚本必须在 32 位那个解释器里跑,装 64 位后台包不能加速这件事,只会让人误以为装错了。

提示:判断当前解释器对不对,最快的办法是在脚本第一行打印arcpy.mapping.MapDocument这个对象,能取到就是对的,报 AttributeError 基本就是跑进了 64 位环境或者根本没装 Desktop。

2.2 找到那个正确的 python.exe,别用系统里的

机器上很可能同时存在三个 Python:ArcGIS 自带的 2.7、以前装别的工具留下的 3.x、以及某次从官网下的独立 2.7。后两个都不能import arcpy,因为 arcpy 是随 Desktop 安装写进 site-packages 的,路径绑死在安装目录下。

标准路径长这样:

C:\Python27\ArcGIS10.2\python.exe # 32 位,Desktop 自带,出图用这个 C:\Python27\ArcGISx6410.2\python.exe # 64 位后台处理,arcpy.mapping 不可用 C:\Python27\python.exe # 独立安装,通常没有 arcpy

验证方式很直接,开个命令提示符敲:

"C:\Python27\ArcGIS10.2\python.exe" -c "import arcpy; print(arcpy.GetInstallInfo()['Version'])"

能打印出 10.2 之类的版本号就说明解释器对了。这一步看着傻,但我见过太多人卡在ImportError: No module named arcpy,最后一问,是在 PyCharm 里配了个 Python 3.9。如果你的机器是 10.3、10.5 或 10.8,把路径里的 10.2 换成对应版本号即可,其余不用动。

2.3 让 Notepad++ 的绿色三角变成脚本运行器

项目里提到用 notepad++ 执行 Python 方便一点,这个思路是对的:mpd 文件改一次就要重跑,反复开命令行太累。Notepad++ 自带「运行」菜单可以绑命令,配置一次就能按快捷键出图。

菜单「运行 → 运行」(英文版 Run → Run),输入框里填:

cmd /k "C:\Python27\ArcGIS10.2\python.exe" "$(FULL_CURRENT_PATH)"

点「保存」,给它起个名字比如Py27_ArcGIS,顺手指定一个不冲突的快捷键,比如 Ctrl+Alt+F9。$(FULL_CURRENT_PATH)是 Notepad++ 的宏,运行时会替换成当前打开的 .py 文件的完整路径,所以脚本另存为什么名字、放在哪个盘都能适配。前面的cmd /k是为了让窗口跑完后停住,方便看print出来的图斑编号和报错堆栈;如果用cmd /c,窗口一闪就关,出错了根本看不见原因。

如果装了 NppExec 插件,也可以在插件里加一条C:\Python27\ArcGIS10.2\python.exe "$(FULL_CURRENT_PATH)",效果一样,区别是 NppExec 支持把输出面板嵌在编辑器下方,滚日志更方便。我个人的习惯是主用「运行」菜单,因为它不依赖插件,换台机器也能立刻配好。

2.4 先建好四个文件夹,别把路径写成面条

批量出图的报错里,有一半是路径问题:目录不存在、路径里有空格、路径里有中文、mxd 里存的是绝对路径换台机器就断。开工前先把目录结构定下来,后面改脚本只改四个变量。

目录用途命名建议
layout存 .mxd 和图层文件全英文,无空格
output存导出的 JPG按批次日期分子目录
script存 .py 脚本与 mxd 同级
log存运行日志和错误清单一次出图追加一个文件

路径里带空格是最常见的隐形坑:D:\My Work\...这种,在 Python 里拼字符串没事,但一旦走到命令行或者某些旧接口,空格会被截断。中文路径在 10.2 的 Python 2.7 下也容易触发编码问题,尤其是print中文文件名的时候。统一用英文加下划线的路径,能省下后面一半的排查时间。

3. 数据驱动页面配置:图层、名称字段、排序与动态文本

3.1 启用 Data Driven Pages 并锁定索引图层

打开 ArcMap,把卫片图斑图层加载进来,确认属性表里有唯一标识字段(图斑编号之类)和要做进图里的信息字段(所在村、面积、类型)。然后在工具栏空白处右键,或者在菜单里走「自定义 → 工具栏 → 数据驱动页面」(英文版 Customize → Toolbars → Data Driven Pages),调出这个小工具栏。

点第一个按钮「设置数据驱动页面」,弹出设置窗口。这里最关键的一项是「图层」(Layer):选你的图斑图层作为索引图层。选错这一项是后面所有问题的源头——如果选成了底图或者行政区面,页面数量会变成行政区个数,出图数量和文件名全乱。

其余几项一次配好:

  • 名称字段(Name Field):决定每页的页名,也就是后面脚本里拿来做文件名的字段。选图斑编号,前提是唯一;如果有重复编号,导出时会互相覆盖,出图数量对不上。
  • 排序字段(Sort Field):决定 1 号页面到 N 号页面按什么顺序排。一般按编号升序,方便和清单核对;按面积降序也可以,取决于交付要求。
  • 显示范围(Extent):常用「居中并缩放至要素」(Center and Scale to Feature),让每页都以当前图斑居中。
  • 比例尺(Scale):这里有个取舍,见下一节。

配完之后点「确定」,页数会显示在工具栏上,比如「1 / 327」。这个数字很关键,记住它,脚本跑完后要靠它核对张数。

3.2 名称字段与排序字段:出图文件名和顺序的源头

名称字段不只是显示用。脚本里mxd.dataDrivenPages.pageNameField.name拿到的是这个字段的字段名,pageRow.getValue(字段名)拿的是当前页对应要素在该字段上的值。换句话说,脚本从来没往文件名里塞过自己的编号逻辑,文件名完全由你在这一步选定的字段决定。

所以如果客户要的文件名是「村名_面积」,那条路不是改脚本,而是在图斑图层里新建一个文本字段,用字段计算器拼好,比如村名 + "_" + 编号,再把这个字段设为名称字段。字符串拼接在 Python 里是+,但在字段计算器里要注意两个都是文本类型,数字字段要先str()转换,否则会报类型不匹配。这一步做好了,后面脚本会非常干净。

排序字段容易被忽略。默认按 ObjectID 排,导出顺序看着没问题,但跟交付清单对不上。实际做法是把排序字段设成图斑编号,然后导出来的文件按名称排序就是清单顺序,核对张数时一眼就能看出缺了哪一号。如果编号是「1、2、3、10、11」这种,按文本排序会变成「1、10、11、2、3」,要按数值排就得建一个整型排序字段,或者把编号补零成定长文本。这种细节不做,交付时对方按名字一扫就发现顺序乱。

3.3 比例尺与显示范围的取舍:定死还是跟随图斑

比例尺的设置有两种典型做法,选哪种取决于出图用途。

第一种是「<自定义>」,也就是每个图斑按自己范围缩放。好处是小图斑也能看清,坏处是同一批图里比例尺各不相同,出图后尺度和面积没法横向比较,做影像判读的人会抱怨。第二种是给一个固定比例尺,比如 1:2000,所有页统一。好处是横向可比、版面统一;坏处是遇到特别大的图斑会被裁掉一部分,遇到特别小的图斑周围留白太多。

我的做法是折中:先把图斑按面积分档,比如小于 5 亩、5 到 50 亩、大于 50 亩分三批,每批用一个固定比例尺,脚本按批次跑三次。这样既保证批内一致,又不至于让一张图全是空白或者全被裁切。分档的依据写在 mxd 的图层定义查询里,或者干脆做三个 mxd,各有各的 Data Driven Pages 设置,脚本换个 mxd 路径就行。

显示范围如果是「仅缩放至要素宽度」或者「要素宽度和高度百分比」,要注意宽高比和图框不一致时会留下大块空白。图框是 A4 横向的话,比例大致 1.41:1,图斑如果是细长条,无论怎么居中都会有大量留白。这种时候要么改图框方向,要么接受留白并在动态文本里补上周边信息。

3.4 布局动态文本:让村名、面积、类型跟着图斑走

切到布局视图(Layout View),这是出图的面子。图框、图例、比例尺、指北针摆好之后,真正让每张图「不一样」的是动态文本。

插入方式:菜单「插入 → 动态文本」,会看到几类可选:页面名称、页面属性、数据框属性、当前日期、用户等。「页面名称」插进去就是当前页的名称字段值,也就是图斑编号,这个是必加的。「页面属性」这一项才能取到图斑的其他字段,比如所在村、面积、类型,插入的时候会让你选字段,选完在版面上显示成一串类似<dyn type="page" property="属性值" attribute="所在村"/>的标记,切页预览时会自动变成实际值。

排版上我会把动态文本和静态标签分开摆:左边灰字「图斑编号:」是静态文本,右边黑字是动态文本,这样用户一眼能分清哪些是变动的。面积字段如果需要在图上带单位,字段计算器里先拼好带「亩」或「平方米」的字符串再插入,比在版面上做后处理省事。

还有一个小技巧:动态文本支持在同一个文本框里混排。把「图斑编号:」和页面名称动态文本放在一个框里,调整字号和颜色,出图后版面会整齐很多,不用每个元素单独对齐。数量不多的字段可以这么堆,超过四五个字段就该考虑做属性表格元素了。

3.5 打开页面定义并保存 mxd

这一步是「邻居图斑跑到当前页上」的解药。默认情况下,数据框里所有要素都会画出来,翻到第 5 页时,第 4 页和第 6 页的图斑也躺在画面边缘,看着不算错,但交付出去很业余。

设置方法:右键数据框 → 属性 → 数据框选项卡,勾选「启用」页面定义,并在下方选择「裁剪到索引要素的轮廓」或者「裁剪到索引要素的外接矩形」。前者贴合多边形形状,后者更方正,看图习惯上后者更常见。勾完之后再翻页,画面里就只剩当前图斑和它周围的底图。

最后保存 mxd。保存前有件事值得做:文件 → 地图文档属性 → 路径名,勾选「存储相对路径名」。这样整个layout目录连同里面的数据一起拷给别人,mxd 不会因为盘符不同而断链。如果数据源本来就分散在多个盘,那就别勾,改成先用「数据 → 打包地图」把数据收拢。

保存完,先手动翻三五页看看版面和动态文本对不对,确认没问题再去写脚本。脚本只能复制你配好的东西,配错了它只会批量复制错误。

4. 批量出图脚本:arcpy.mapping 逐页导出与参数调整

4.1 脚本骨架:把八行代码逐行拆开

下面这份是在 10.2 的 Python 2.7 下跑通的版本,和项目里给的思路一致,但补了几处实际会踩的细节。

# coding:utf-8 import arcpy, os MXD_PATH = r"D:\GIS_Work\batch_export\layout\spot_check.mxd" OUT_DIR = r"D:\GIS_Work\batch_export\output\20240601" mxd = arcpy.mapping.MapDocument(MXD_PATH) # 输出目录不存在会直接抛错,先兜一层 if not os.path.exists(OUT_DIR): os.makedirs(OUT_DIR) page_count = mxd.dataDrivenPages.pageCount # 页面总数,用来核对张数 name_field = mxd.dataDrivenPages.pageNameField.name # 名称字段的字段名 # range 右开区间,必须 +1,否则最后一页永远出不来 for page_num in range(1, page_count + 1): mxd.dataDrivenPages.currentPageID = page_num # 切到第 N 页 map_name = mxd.dataDrivenPages.pageRow.getValue(name_field) # 取当前页名称值 out_jpg = os.path.join(OUT_DIR, str(map_name) + ".jpg") arcpy.mapping.ExportToJPEG(mxd, out_jpg, resolution=200, jpeg_compression_quality=90) print "page %d/%d -> %s" % (page_num, page_count, map_name) del mxd # 释放文件锁,否则 ArcMap 会一直占着 mxd print "ok"

第一行# coding:utf-8不是装饰,Python 2.7 默认按 ASCII 解析源码,脚本里只要出现一个中文注释就报 SyntaxError,这行声明是必须的。

arcpy.mapping.MapDocument(MXD_PATH)打开的是一个「文档对象」,不是普通文件句柄。它会把 mxd 引用的所有图层、布局元素一起加载进来,因此这个脚本能在 ArcMap 完全关闭的情况下独立跑,前提是解释器是 Desktop 自带那个 32 位版本。

pageCount是当前索引图层的要素数量,也就是总页数。这个值最好在出图前打印一次,和你记的「327」对一下,不一致说明索引图层选错了或者定义查询过滤掉了一部分要素。

循环体里三行做三件事:切页、取名、导出。currentPageID赋值之后,pageRow才指向新的一页,顺序不能反,先取名字再切页会拿到上一页的值。getValue需要传字段名而不是字段别名,如果图层里字段别名是中文、字段名是TBBH,这里必须写TBBH。

ExportToJPEG的第一个参数是文档对象,第二个是输出路径,后面的都是可选参数。文件扩展名决定不了格式,是函数本身决定的,用ExportToJPEG却给.png后缀,出来的还是 JPEG 内容,改后缀名打不开。要出 PNG 就换成ExportToPNG,两个函数的参数表不完全一样,混着传会报意外关键字参数。

最后del mxd别省。跑完不释放,ArcMap 里那个 mxd 会一直处于被占用状态,下次想改布局会发现保存不了,只能关掉重开。

4.2 输出格式与分辨率:PNG 还是 JPEG,DPI 给多少

格式选择看用途。要打印、要保证线条和图例文字清晰,选 PNG,无损压缩,代价是文件体积大,三百多张能到几个 G。要发给甲方看、要贴进报告,选 JPEG,指定压缩质量,体积小很多。

分辨率参数resolution的单位是 DPI,和布局页面的物理尺寸相乘得到像素尺寸。A4 横向是 11.69 × 8.27 英寸,200 DPI 大约是 2338 × 1654 像素,300 DPI 是 3507 × 2481。我的经验值是:

用途格式DPI单张体积参考
汇报 PPT 内嵌JPEG150300 KB ~ 600 KB
报告插图JPEG200600 KB ~ 1.2 MB
打印出图PNG3008 MB ~ 20 MB
存档备查PNG2003 MB ~ 8 MB

JPEG 的jpeg_compression_quality取值 1 到 100,90 以上肉眼基本看不出压缩痕迹,再往上体积涨得比画质快,不划算。如果画面里有大面积均匀色块(比如大片耕地),质量给太低会出现明显的块状伪影,边缘发糊,这时候要么提到 95,要么换成 PNG。

还有一个参数容易被误解:df_export_width和df_export_height。这两个是以像素计的导出宽高,一旦显式指定,页面尺寸就不起作用了,DPI 参数的效果也会被覆盖掉一部分。所以除非有明确的像素要求(比如系统上传限制 1920 宽),否则不传这两个参数,让它按页面尺寸乘 DPI 走,最省心。

4.3 文件名清洗:编号里有斜杠、空格、中文怎么办

真实数据的编号字段很少是干净的。会有2024-01/02这种带斜杠的,会有前后带空格的,会有全角的括号。直接拿来做文件名,轻则建出一堆带下划线的怪名字,重则因为路径里有非法字符直接异常中断,跑到第 137 页停下,后面全废。

一个稳定的做法是加一层清洗函数:

# coding:utf-8 import re ILLEGAL = re.compile(r'[\\/:*?"<>|\s]') def safe_name(raw, fallback): # str 在 2.7 里是字节串,中文要先按 gbk 解码,否则 unicode() 会按 ascii 炸掉 if isinstance(raw, str): text = raw.decode("gbk", "ignore") else: text = unicode(raw) text = text.strip() text = ILLEGAL.sub("_", text) # Windows 文件名禁用字符统一换成下划线 if not text: return fallback # 全被清空时用序号兜底,保证不重名 return text.encode("gbk")

ILLEGAL里的字符集是 Windows 文件名的硬性限制,反斜杠和正斜杠会把一个名字拆成两级目录,冒号和问号在部分文件系统上会静默失败,星号和尖括号在共享盘上会被拦截。空格也一并替换掉,避免后续用批处理或命令行处理时被拆参数。

decode("gbk", "ignore")里的ignore是保命参数,遇到个别残缺字节直接跳过,不至于让整批任务因为一个脏数据停掉。代价是极少数名字会少一两个字,但比起中断,这个代价可以接受。

fallback建议传"page_%d" % page_num,这样万一某个图斑名称字段是空的,文件名叫page_137.jpg,你事后还能靠页码反查是哪一条。

调用方式改成:

map_name = mxd.dataDrivenPages.pageRow.getValue(name_field) out_jpg = os.path.join(OUT_DIR, safe_name(map_name, "page_%d" % page_num) + ".jpg")

4.4 加一层日志和错误跳过:一批三百张不能死在第一百张

纯循环最大的问题是脆弱:第 137 个图斑的几何有问题、或者名称重复导致权限冲突,整个脚本抛异常退出,前面 136 张白跑不说,你还得从头再来一遍。生产环境里我会把循环体包一层 try,把失败项记进日志,让它继续往下跑。

# coding:utf-8 import arcpy, os, traceback LOG_PATH = r"D:\GIS_Work\batch_export\log\export.log" fail = 0 with open(LOG_PATH, "a") as log: for page_num in range(1, page_count + 1): try: mxd.dataDrivenPages.currentPageID = page_num map_name = mxd.dataDrivenPages.pageRow.getValue(name_field) out_jpg = os.path.join(OUT_DIR, safe_name(map_name, "page_%d" % page_num) + ".jpg") arcpy.mapping.ExportToJPEG(mxd, out_jpg, resolution=200, jpeg_compression_quality=90) log.write("OK\t%d\t%s\n" % (page_num, map_name)) except Exception, e: # 2.7 的写法,3.x 要改成 except Exception as e fail += 1 log.write("FAIL\t%d\t%s\t%s\n" % (page_num, map_name, e)) traceback.print_exc() # 屏幕上也留一份,方便当场定位 print "done, failed = %d" % fail

except Exception, e是 Python 2 的语法,直接抄到 3.x 里会报 SyntaxError,反过来也一样。这一点在混装多版本 Python 的机器上尤其要注意,改脚本前先确认解释器版本。

日志用制表符分隔,跑完直接拖进 Excel 分列,FAIL那几行就是需要单独处理的。traceback.print_exc()打在屏幕上,第一次跑的时候盯着看,前几条报错往往能暴露出共性问题,比如全部失败说明是目录权限,零星失败说明是个别要素几何异常。

失败项怎么补:把FAIL行的页码记下来,在 ArcMap 里手动翻到那一页看是什么情况,多半是图斑为空几何、或者名称字段重复导致覆盖。前者在索引图层上做个定义查询排掉,后者回上一章改名称字段的拼接规则。

5. 避坑与排查:五条踩过的记录

5.1 图斑一共 327 个,导出只有 326 张

现象:脚本跑完打印ok,日志里也没报错,去 output 目录一数,少一张。翻到最后发现编号最大那个图斑没有对应文件。

原因:range(1, mxd.dataDrivenPages.pageCount)是右开区间,pageCount本身取不到。项目原文的示例就是这么写的,照抄必踩。

解决:改成range(1, page_count + 1)。改完之后在脚本里加一句输出,print "total=%d, exported=%d" % (page_count, len(os.listdir(OUT_DIR))),两个数不一致就别急着交付。

5.2 报错说 MapDocument 没有 dataDrivenPages 属性

现象:脚本第一行打开 mxd 没问题,走到mxd.dataDrivenPages直接抛AttributeError: 'MapDocument' object has no attribute 'dataDrivenPages'。

原因:mxd 里根本没启用数据驱动页面。可能是配完之后没点确定,也可能是保存时切到了别的 mxd。另一种可能是这台机器上的解释器不是 Desktop 自带的那个,弧py 版本对不上。

解决:回到 ArcMap 打开那个 mxd,调出数据驱动页面工具栏,看页数是不是正常显示「1 / N」。不显示就重新设置一遍并保存。确认 mxd 没问题还报错,就去查解释器路径,用 2.2 节那条命令验证版本号。

5.3 导出来的图是空白的,只有图框和指北针

现象:图框、图例、比例尺都在,中间的数据区一片白,或者只有底图没有图斑。

原因:mxd 里的数据源路径断了。常见于从别人机器上拷过来的 mxd,或者把数据从一个盘挪到了另一个盘。数据驱动页面的索引还在,所以页数正常,但图层加载不出来。

解决:ArcMap 里打开 mxd 时会弹「数据源无效」的提示,别点忽略。用「文件 → 地图文档属性」勾上「存储相对路径名」,然后把 mxd 和数据放在同一个父目录下,重新指定一次数据源。批量出图前先手动导一张看一眼,这三十秒能省掉后面半小时的重跑。

5.4 跑到一半停了,报 UnicodeEncodeError

现象:前几十张正常,到某个图斑突然抛UnicodeEncodeError: 'ascii' codec can't encode characters,位置在拼接路径或 print 那一行。

原因:Python 2.7 里str和unicode混用,中文名称在转换成字节串时默认按 ASCII 编码。print到 cmd 窗口时也会触发,因为控制台默认代码页是 936,但 Python 的输出流编码不一定是。

解决:所有字符串在参与路径拼接和输出前统一处理一遍,参考 4.3 节的safe_name。print中文出问题,可以在脚本头部加:

# coding:utf-8 import sys reload(sys) sys.setdefaultencoding("gbk") # 只影响当前进程,改完能用但不推荐长期依赖

reload(sys)这两行是 Python 2 的权宜之计,能让默认编码变成 gbk,代价是全局副作用。更干净的做法是全程用 unicode 内部处理,只在最后落盘时编码一次,但脚本一长就容易漏,所以我一般还是带着这两行跑批处理。

5.5 换台机器,脚本第一句就报路径不存在

现象:在自己机器上跑得好好的脚本,拷到同事机器上,MapDocument打开就报文件不存在。

原因:mxd 路径是写死的绝对路径,脚本里的MXD_PATH也是写死的。另外原脚本的输出路径可能指向一个不存在的盘符。

解决:把路径从脚本里提出来,改成相对于脚本位置的写法,脚本和 mxd 一起拷就能跑:

# coding:utf-8 import os, arcpy BASE = os.path.dirname(os.path.abspath(__file__)) # 脚本所在目录 MXD_PATH = os.path.join(BASE, "layout", "spot_check.mxd") OUT_DIR = os.path.join(BASE, "output")

os.path.abspath(__file__)拿到脚本的绝对路径,dirname取上级目录,后面所有路径都从这个基准拼出去。换盘、换机器、换中文目录都能自适应。这个改动只有三行,但从此不用每次改路径。

6. 装完怎么验证:三张抽样图、一张核对表、一条耗时基线

6.1 先抽三张:首图、中间图、末图

脚本打印ok不算跑通,只能算跑完。我的验收习惯是固定抽三张:第 1 页、中间某一页、最后一页。这三张能覆盖绝大多数问题——首图验配置有没有生效,中间图验批量过程有没有偏移,末图验循环边界有没有漏。

每张图对着三样东西看:图斑形状是否居中、动态文本里的编号和文件名是否一致、比例尺数值是否在预期范围内。第三项最容易被忽略,尤其是用了「<自定义>」比例尺的批次,抽到的三张比例尺应该各不相同,如果三张一模一样,说明自定义没生效,所有页都用了同一个固定值。

再补一个反查:随便挑一张图,在 ArcMap 里用属性查询定位到那个图斑,量一下图上距离,和图上的比例尺对一下。差得离谱就说明导出时的 DPI 和页面尺寸算错了,回头查resolution参数。

6.2 用清单核对张数,别用眼睛数

三百多个文件靠数是不可能数的,用命令行一行就出结果:

dir /b "D:\GIS_Work\batch_export\output\20240601\*.jpg" | find /c /v ""

输出一个数字,和脚本打印的page_count对一下。相等只能说明数量够,还要验有没有重名覆盖——把文件名列表导出来排序,看有没有两个图斑对应同一个名字。做法是回到 ArcMap 的属性表,对名称字段做一次汇总统计,最大值和记录数对比,如果最大值对应的重复次数大于 1,说明这个字段不唯一。

核对项期望值不通过时的排查方向
文件总数等于 pageCount循环边界、目录权限
文件名唯一无重复名称字段拼接规则
抽样版面图斑居中、文本正确页面定义、动态文本绑定
抽样比例尺符合设定数据驱动页面比例尺选项
单张可打开无损坏导出中断、磁盘空间

6.3 记一条耗时基线,下次出问题能第一时间发现

第一次跑通的时候顺手记一下耗时,这个数字以后就是你的报警线。

echo %time% && "C:\Python27\ArcGIS10.2\python.exe" "D:\GIS_Work\batch_export\script\batch.py" && echo %time%

在 10.2、200 DPI、JPEG 质量 90 的条件下,一张图大概 0.8 到 1.5 秒,三百多张在五到八分钟。如果某次跑到了二十分钟,基本可以断定是某一页的图层查询变慢了,或者输出目录被打到了网络盘上。我遇到过的最离谱一次是四十多分钟,查下来是 mxd 里挂了一个指向网络共享的影像服务图层,每翻一页都要重新拉一次瓦片,把那个图层移除后立刻回到七分钟。

耗时异常的另一个常见原因是del mxd忘了写,脚本跑完后 ArcMap 里那个文档还锁着,下次再跑就得等锁释放,表现出来就是启动阶段卡很久。

从那以后我每次批量出图都强制走一遍这套验收:先打 pageCount,再看日志里 FAIL 的行数,然后抽三张图对字段,最后记一个耗时。四步走完才敢把文件夹发出去。这套流程看着笨,但它救过我两次——一次是名称字段有重复导致静默覆盖,一次是最后一页漏掉,都是靠张数核对和末图抽样揪出来的。希望这套装法能帮到你,少走几趟我已经走过的弯路。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询