ArcPy入门学习指南(含:arcpy in_memory的详细解答)
很多团队在做 ArcGIS 地理处理时,最头疼的是“明明只是临时中间结果,却要频繁落盘到 GDB 或 Shapefile,速度慢、磁盘乱”。作为长期做 Python 与地理处理自动化的从业者,我的经验是:合理利用 ArcPy 的 in_memory 工作空间,可以显著减少磁盘 I/O、提速流水线,还能让脚本更整洁、可维护。
ArcPy 与 in_memory:是什么
ArcPy 是 ArcGIS Pro/ArcMap 提供的 Python 地理处理接口,覆盖数据管理、分析、制图与自动化。in_memory 工作空间可以理解为一个“驻留内存的虚拟地理数据库”,在 Python 进程生命周期内存在(会话结束即释放),支持大多数地理处理工具的中间结果存取(表与要素类为主)。
用一个类比:如果把整条分析流程比作装配线,那么磁盘上的文件就像仓库货架,上架/下架都要搬运;而 in_memory 更像是工作台上的临时托盘,拿取与放回几乎零搬运(I/O),速度自然快。
为什么要用 in_memory
- 性能:减少磁盘读写,常见缓冲、叠置、字段计算等场景可显著缩短耗时。
- 整洁:中间结果不落盘,避免临时数据污染工程目录。
- 可组合:链式调用更顺滑,便于快速搭建与迭代分析流水线。
- 资源亲和:内存可就地复用对象,减少碎片化读写。
核心提示:in_memory 适合“中间态、可丢弃”的临时数据。对需要持久化、复查或共享的成果,仍应及时 CopyFeatures 到文件地理数据库。
基本用法与代码模板
以下示例以 ArcGIS Pro 环境为参考,演示把中间结果放到内存、最终结果落盘的常见模式。
# -*- coding: utf-8 -*-
import arcpy
import time
# 环境配置
arcpy.env.overwriteOutput = True # 允许覆盖输出(谨慎使用)
arcpy.env.workspace = "in_memory" # 把当前工作空间设置为内存
# 输入与输出
in_fc = r"C:datatransport.gdbroads"
out_fc = r"C:dataoutput.gdbroads_buf_diss"
t0 = time.perf_counter()
# 1) 在内存中做缓冲
buf_fc = "roads_buf" # 因为 workspace= in_memory,可直接用名称
arcpy.analysis.Buffer(in_fc, buf_fc, "50 Meters", dissolve_option="NONE")
# 2) 在内存中溶解以减少冗余
diss_fc = "roads_buf_diss"
arcpy.management.Dissolve(buf_fc, diss_fc)
# 3) 最终结果落盘到文件地理数据库
arcpy.management.CopyFeatures(diss_fc, out_fc)
print(f"流程耗时:{time.perf_counter() - t0:.2f}s")
# 4) 清理内存中的中间结果(可选)
arcpy.management.Delete([buf_fc, diss_fc])
要访问内存中的对象,可用 in_memory/名称
的显式路径,或通过 arcpy.EnvManager
暂时切换工作空间:
# 显式路径写法
arcpy.Exists("in_memory/roads_buf")
# 上下文管理器写法,便于枚举删除
with arcpy.EnvManager(workspace="in_memory"):
for fc in arcpy.ListFeatureClasses():
arcpy.management.Delete(fc)
创建唯一临时名称与存在性检查
避免命名冲突是稳定自动化的关键。推荐结合 CreateUniqueName 与 Exists:
tmp_fc = arcpy.CreateUniqueName("tmp", "in_memory") # 自动生成不重复名称
arcpy.analysis.Buffer(in_fc, tmp_fc, "100 Meters")
if arcpy.Exists(tmp_fc):
cnt = int(arcpy.management.GetCount(tmp_fc)[0]) # 获取要素数量
print(f"临时要素数:{cnt}")
与数据访问模块(arcpy.da)的配合
在内存要素类上使用 arcpy.da 游标,可避免额外磁盘读写:
# 统计内存缓冲结果的面积总和(投影坐标系下)
total_area = 0.0
with arcpy.da.SearchCursor("in_memory/roads_buf", ["SHAPE@AREA"]) as cur:
for row in cur:
total_area += row[0]
print(f"缓冲区总面积:{total_area:.2f}")
性能对比的最小实验
下面给出一个可复现的“小基准”,比较 in_memory 与地理数据库输出的速度(以缓冲为例):
import time
import arcpy
arcpy.env.overwriteOutput = True
in_fc = r"C:datatransport.gdbroads"
# A) in_memory
t0 = time.perf_counter()
arcpy.analysis.Buffer(in_fc, "in_memory/roads_buf", "30 Meters")
t_inmem = time.perf_counter() - t0
# B) FileGDB
t1 = time.perf_counter()
arcpy.analysis.Buffer(in_fc, r"C:datascratch.gdbroads_buf", "30 Meters")
t_gdb = time.perf_counter() - t1
print(f"in_memory:{t_inmem:.2f}s, GDB:{t_gdb:.2f}s")
在典型机械盘或网络盘环境中,in_memory 往往有明显优势;SSD 上收益依然存在,但幅度会随数据量与工具类型而变化。
最佳实践与清理策略
- 只把中间结果放内存:可丢弃的数据放 in_memory,阶段性成果及时 CopyFeatures 到 GDB。
- 控制名称生命周期:用
CreateUniqueName
或时间戳命名,避免覆盖与串扰。 - 显式删除:流程末尾
arcpy.management.Delete
清理,长管线中分段清理降低峰值内存。 - 分块处理:超大数据按网格/行政区切块到内存处理,阶段成果落盘,再汇总。
- 失败兜底:异常时也要清理,结合 try/finally 确保 Delete 执行。
# try/finally 保障清理
tmp1, tmp2 = "in_memory/a", "in_memory/b"
try:
arcpy.analysis.Buffer(in_fc, tmp1, "100 Meters")
arcpy.management.Dissolve(tmp1, tmp2)
arcpy.management.CopyFeatures(tmp2, out_fc)
finally:
for ds in (tmp1, tmp2):
if arcpy.Exists(ds):
arcpy.management.Delete(ds)
常见问题与易错点
- 支持的数据类型:以要素类与表为主;对栅格数据集的直接写入通常不受支持(请落盘到 GDB/TIFF,或使用栅格对象工作流)。
- 路径写法:统一使用
in_memory/名称
,或把arcpy.env.workspace
设为in_memory
后用短名。 - 会话生命周期:Python 进程结束即释放;ArcGIS Pro 崩溃或重启后内存数据不可恢复。
- 内存限制:32 位环境(如老版 ArcMap)受限更明显;64 位 ArcGIS Pro 更宽裕,但大数据仍需分块。
- 并行与多进程:ArcPy 通常不线程安全;若用多进程,每个子进程有独立 in_memory 命名空间,注意避免跨进程引用。
- OverwriteOutput:开启覆盖输出有助迭代,但要确保目标名不会被误覆盖关键数据。
- 投影与度量:涉及面积/长度计算前,先投影到合适的等积/等距坐标系,再在内存中计算。
典型场景选择建议
场景 | 是否优先用 in_memory | 备注 |
---|---|---|
缓冲/叠置/选择等中间结果 | 是 | 链式操作快,减少 I/O |
最终成果产出/归档 | 否 | 落盘到 GDB 或企业级数据源 |
海量数据(> 数百万要素) | 视内存而定 | 建议分块,阶段性落盘 |
栅格分析 | 通常不适用 | 请使用栅格对象或文件输出 |
小案例:一次性分析脚本的“内存优先”重构
目标:对站点要素进行 300m 缓冲,求与地块相交面积,并输出 TOP10 结果。除最终表外,全部放在内存中进行。
# 输入
sites = r"C:projcity.gdbpoi_station"
parcels = r"C:projcity.gdbparcels"
out_table = r"C:projresult.gdbpoi_parcel_top10"
arcpy.env.overwriteOutput = True
arcpy.env.workspace = "in_memory"
# 1) 站点缓冲(内存)
buf = "sites_buf"
arcpy.analysis.Buffer(sites, buf, "300 Meters", dissolve_option="NONE")
# 2) 与地块相交(内存)
inter = "buf_parcel_inter"
arcpy.analysis.Intersect([buf, parcels], inter)
# 3) 计算相交面积(新增字段,内存)
arcpy.management.AddField(inter, "A_m2", "DOUBLE")
arcpy.management.CalculateField(inter, "A_m2", "!shape.area@SQUAREMETERS!", "PYTHON3")
# 4) 汇总每个站点的相交面积(内存)
stat_tbl = "stat_by_site"
arcpy.analysis.Statistics(inter, stat_tbl, [["A_m2","SUM"]], case_field="SITE_ID")
# 5) 选出 TOP10 并落盘
# 说明:内存表可作为 Select 工具输入,结果落盘到 GDB
top10_tbl = "top10"
arcpy.management.SelectLayerByAttribute # 占位说明:如需更复杂排序/取前N,可落盘后用 SQL 处理
arcpy.management.CopyRows(stat_tbl, out_table) # 简化:此处可替换为排序+取前N的具体实现
# 6) 清理(可选)
for ds in [buf, inter, stat_tbl, top10_tbl]:
if arcpy.Exists(ds):
arcpy.management.Delete(ds)
上例突出一个重构思路:把所有可丢弃的中间态留在内存,I/O 最后一跳再落盘。实际项目中可将“排序取前 N、字段派生”等逻辑进一步完善。
进阶建议:与 scratchGDB 搭配
当中间结果需要短暂持久化(例如跨会话复用、人工复核),可将关键阶段输出写入 arcpy.env.scratchGDB,其余仍留在 in_memory:
arcpy.env.scratchGDB # 系统临时地理数据库路径
key_stage = arcpy.CreateUniqueName("stage1", arcpy.env.scratchGDB)
arcpy.management.CopyFeatures("in_memory/roads_buf_diss", key_stage)
结语
总结来说,在 ArcPy 自动化中优先采用 in_memory 承载中间结果,是“既快又稳”的工程化选择:一方面显著减少 I/O 加速流程,另一方面通过命名规范与清理策略保证脚本结构清晰、资源安全。你在自己的项目里,最想把哪段“慢得让人抓狂”的流程改造成内存优先?欢迎留言交流,也可访问 GIS研习社(gisyxs.com)获取更多实践案例。
参考文献
- Esri. The in-memory workspace — ArcGIS Pro documentation. https://pro.arcgis.com/en/pro-app/latest/help/analysis/geoprocessing/basics/the-in-memory-workspace.htm
- Esri. Buffer (Analysis). https://pro.arcgis.com/en/pro-app/latest/tool-reference/analysis/buffer.htm
- Esri. Dissolve (Data Management). https://pro.arcgis.com/en/pro-app/latest/tool-reference/data-management/dissolve.htm
- Esri. Delete (Data Management). https://pro.arcgis.com/en/pro-app/latest/tool-reference/data-management/delete.htm
- Esri. CreateUniqueName (arcpy). https://pro.arcgis.com/en/pro-app/latest/arcpy/functions/createuniquename.htm
- Esri. Exists (arcpy). https://pro.arcgis.com/en/pro-app/latest/arcpy/functions/exists.htm
- Esri. ListFeatureClasses (arcpy). https://pro.arcgis.com/en/pro-app/latest/arcpy/functions/listfeatureclasses.htm
- Esri. Overwrite Output (Environment setting). https://pro.arcgis.com/en/pro-app/latest/tool-reference/environments/overwrite-output.htm
-
gis python 开发入门全解析,gis Python新手指南 2025-09-06 12:13:26
-
gis python开发者必看,gis Python基础入门全解析 2025-09-06 12:13:25
-
gis Python入门指南,从解析gis python基础知识谈起 2025-09-06 12:13:24
-
gis Python入门指南,从解析Gis python库开始 2025-09-06 12:13:23
-
ArcPy实用教程,详解arcpy describe的核心用法 2025-09-02 15:03:03
-
ArcPy入门学习指南(含:arcpy documentation的详细解答) 2025-09-02 15:03:02
-
ArcPy入门学习指南(含:arcpy make feature layer的详细解答) 2025-09-02 15:03:01
-
ArcPy实用技巧解析(含arcpy export features详细讲解) 2025-09-02 15:03:00
-
ArcPy入门详解(含arcpy map核心应用解析) 2025-09-02 15:02:59
-
ArcPy入门学习指南(含:arcpy python的详细解答) 2025-09-02 15:02:59
-
ArcPy入门全指南(附arcpy reference详细解析) 2025-09-02 15:02:58
-
ArcPy核心用法详解(含arcpy copy features实战教程) 2025-09-01 11:21:12
-
ArcPy核心教程,详解arcpy copy features实用方法 2025-09-01 11:21:11
-
ArcPy入门详解(含arcpy基础知识与实用技巧) 2025-09-01 11:21:11
-
ArcPy实用技巧详解(含arcpy spatial join操作方法) 2025-09-01 11:21:10
-
ArcPy入门教程(含arcpy documentation详细解析) 2025-09-01 11:21:09
-
ArcPy基础教程,详解arcpy export features的实现方法 2025-09-01 11:21:08
-
ArcPy实用教程(含arcpy list fields的详细解析) 2025-09-01 11:21:07
-
ArcPy教程详解(含arcpy select by attribute实用方法) 2025-09-01 11:21:06
-
ArcPy入门详解(含arcpy make feature layer实用教程) 2025-09-01 11:21:06